BZOJ 1176 MOKIA

cdq分治。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 2000500
#define maxq 400050
using namespace std;
int s,w,type,a,b,c,d,cnt=0,m=0,ans[maxq];
struct ques
{
    int val,opt,x,y,pos,id;
}q[maxq],tmp[maxq];
int t[maxn];
bool cmp(ques a,ques b)
{
    if ((a.x==b.x) && (a.y==b.y)) return a.opt<b.opt;
    if (a.x==b.x) return a.y<b.y;
    return a.x<b.x;
}
int lowbit(int x)
{
    return (x&(-x));
}
void add1(int x)
{
    scanf("%d%d%d",&a,&b,&c);
    q[++m].id=m;q[m].pos=0;q[m].val=c;q[m].opt=0;
    q[m].x=a;q[m].y=b;
}
void add2(int x)
{
    scanf("%d%d%d%d",&a,&b,&c,&d);
    cnt++;
    q[++m].val=1;q[m].opt=1;q[m].x=c;q[m].y=d;q[m].pos=cnt;q[m].id=m;
    q[++m].val=1;q[m].opt=1;q[m].x=a-1;q[m].y=b-1;q[m].pos=cnt;q[m].id=m;
    q[++m].val=-1;q[m].opt=1;q[m].x=a-1;q[m].y=d;q[m].pos=cnt;q[m].id=m;
    q[++m].val=-1;q[m].opt=1;q[m].x=c;q[m].y=b-1;q[m].pos=cnt;q[m].id=m;
}
void add(int x,int val)
{
    for (int i=x;i<=w;i+=lowbit(i))
        t[i]+=val;
}
int query(int x)
{
    int ret=0;
    for (int i=x;i>=1;i-=lowbit(i))
        ret+=t[i];
    return ret;
}
void cdq(int left,int right)
{
    if (left==right) return;
    int mid=left+right>>1;
    int l1=left,l2=mid+1;
    for (int i=left;i<=right;i++)
    {
        if ((q[i].id<=mid) && (!q[i].opt)) add(q[i].y,q[i].val);
        else if ((q[i].id>mid) && (q[i].opt)) ans[q[i].pos]+=q[i].val*query(q[i].y);
    }
    for (int i=left;i<=right;i++)
        if ((q[i].id<=mid) && (!q[i].opt)) add(q[i].y,-q[i].val);
    for (int i=left;i<=right;i++)
    {
        if (q[i].id<=mid) tmp[l1++]=q[i];
        else tmp[l2++]=q[i];
    }
    for (int i=left;i<=right;i++)
        q[i]=tmp[i];
    cdq(left,mid);cdq(mid+1,right);
}
int main()
{
    scanf("%d%d",&s,&w);
    while (scanf("%d",&type)!=EOF)
    {
        if (type==3) break;
        if (type==1) add1(cnt);
        else add2(cnt);
    }
    sort(q+1,q+m+1,cmp);
    cdq(1,m);
    for (int i=1;i<=cnt;i++)
        printf("%d\n",ans[i]);
    return 0;
}
时间: 2024-08-26 13:37:55

BZOJ 1176 MOKIA的相关文章

BZOJ 1176 Mokia(cdq分治,解决一类在线查询问题)

题意:维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000. 这题在bz是贵族题= =,没有链接了 解法:cdq分治,第一维是时间t,第二维是x,第三维是y:每个操作看作一个三维序(t, x, y):假设修改操作是(t, x, y),两个查询操作分别是(t1, x1, y1) 和 (t1, x2, y2):实际上就要问,有多少个修改操作,满足t<=t1,x1<=x&

bzoj 1176 Mokia(CDQ分治)

[题目链接]  http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=96974 [题意] 定义查询操作与修改操作:1 x y z 为将格子(x,y)修改为z:2 x1 y1 x2 y2为查询以(x1,y1)为左上(x2,y2)为右下的子矩阵之和. [思路] cdq分治. 矩阵初始值都为s,所以先不考虑. 首先明确每一个修改操作都互不影响.然后把每一个对子矩阵的询问操作差分为对四个点的“前缀和”操作. 先把所有的操作按照x升序排列

[bzoj] 1176 Mokia || CDQ分治

原题 给出W×W的矩阵(S没有用,题目有误),给出无限次操作,每次操作的含义为: 输入1:你需要把(x,y)(第x行第y列)的格子权值增加a 输入2:你需要求出以左下角为(x1,y1),右上角为(x2,y2)的矩阵内所有格子的权值和,并输出 输入3:表示输入结束 因为修改之间相互独立,所以可以用CDQ. 三个维度分别为时间,x轴,y轴. 简单的三维偏序即可. #include<cstdio> #include<algorithm> #define N 100010 #define

bzoj 1176 [Balkan2007]Mokia - CDQ分治 - 树状数组

Description 维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000. Input 第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小 接下来每行为一下三种输入之一(不包含引号): "1 x y a" "2 x1 y1 x2 y2" "3" 输入1:你需要把(x,y)(第x行第y列)的格子权值增加a 输入

BZOJ 1176: [Balkan2007]Mokia

一道CDQ分治的模板题,然而我De了一上午Bug...... 按时间分成左右两半,按x坐标排序然后把y坐标丢到树状数组里,扫一遍遇到左边的就add,遇到右边的query 几个弱智出了bug的点, 一是先分了左右两半再排序,保证的是这次的左右是上次没有计算过的贡献, for(int i=l;i<=r;i++) qs[i].k=(i>mid); sort(qs+l,qs+r+1,cmp2); 然后时间的先后是因为一开始就是按时间排好序的已经保证了. 二是矩阵的一个经典的套路就是拆成四部分差分查询.

【BZOJ 1176】 [Balkan2007]Mokia

1176: [Balkan2007]Mokia Time Limit: 30 Sec  Memory Limit: 162 MB Submit: 736  Solved: 306 [Submit][Status] Description 维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000. Input 第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小 接下来每行为一下

【BZOJ 1176】【Balkan 2007】Mokia

http://www.lydsy.com/JudgeOnline/problem.php?id=1176 整体二分的例题 把每个询问拆成四个询问,整体二分里x坐标递增,按x坐标扫的时候用树状数组维护y坐标前缀和. 一开始想复杂了,按cdq分治先solve左边再处理中间再solve右边,这样每次都要对x坐标排序,常数巨大,T了好几次TwT 后来参考了别人的代码,发现自己一开始就想复杂了.这道题不需要在solve完后还是保持原来的按x坐标递增的顺序,也不需要先处理出左边的信息才能更新右边的信息. 这

BZOJ 1176 Balkan 2007 Mokia CDQ分治

题目大意:有一些操作,给一个坐标代表的点加上一个数,和求出一个矩形中的所有数的和. 思路:一眼题,二位树状数组水过. ... .. . 哪里不对?W<=2000000.逗我?这n^2能开下? 这个时候CDQ神牛又来帮助我们了. 这个题应该算是CDQ分治的模板题了吧,简单分析一下,其实不难. 写这个题之前建议写一下BZOJ 1935 SHOI 2007 Tree 园丁的烦恼 树状数组这个题,是本题的简化版. 按照正常的解法,我们应该建立一个二位的数据结构,然后分别维护两维的信息.如果用动态开点的线

[BZOJ 1176&amp;COGS 1752][BOI2007]Mokia(CDQ分治)

Description 维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000. Solution 这道在BZOJ上是权限题啊…然而我在cogs上找到了它 依旧是CDQ分治的论文题,CDQ太强辣… 把查询拆成四个前缀和的形式,在CDQ分治中用时间把操作分为两部分,保证两部分的x各自单调(只有x较小的操作才能对较大的操作产生影响),然后用树状数组维护y这一维 #include<