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

输入2:你需要求出以左下角为(x1,y1),右上角为(x2,y2)的矩阵内所有格子的权值和,并输出

输入3:表示输入结束

Output

对于每个输入2,输出一行,即输入2的答案


题解:
我们可以按照操作的时间,坐标x,坐标y形成三维偏序就好做了

由于操作的时间本身就是有序的,所以不需要排序就可以直接CDQ分治处理坐标x,在坐标x有序的情况下将有贡献的y值放入树状数组记录即可

然后查询做一个简单的容斥拆成4的点询问即可


AC代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
#define pii pair<int,int>
#define mp(a,b) make_pair(a,b)
const int MAXN = 2e5+10;
const int MOD = 100003;
const int INF = 0x3f3f3f3f;
struct node{ int x,y,val,id; }a[MAXN],b[MAXN];
int s,w,tot,cnt,ans[MAXN],q[MAXN];
namespace BIT{
    int bit[MAXN*10];
    inline int lowbit(int x){ return x&-x; }
    inline void add(int x,int val){ for(int i=x;i<=w;i+=lowbit(i)) bit[i]+=val; }
    inline int query(int x,int res=0){ for(int i=x;i;i-=lowbit(i)) res+=bit[i]; return res; }
}
using namespace BIT;
void CDQ(int l,int r){
    if(l>=r) return; int mid=(l+r)>>1;
    CDQ(l,mid); CDQ(mid+1,r);
    int p=l,q=mid+1,x=l;
    while(q<=r){
        while(a[p].x<=a[q].x && p<=mid){
            if(a[p].id==0) add(a[p].y,a[p].val);
            b[x++]=a[p++];
        }
        if(a[q].id) ans[a[q].val]+=query(a[q].y);
        b[x++]=a[q++];
    }
    for(int i=l;i<p;i++) if(a[i].id==0) add(a[i].y,-a[i].val);
    while(p<=mid) b[x++]=a[p++];
    while(q<=r) b[x++]=a[q++];
    for(int i=l;i<=r;i++) a[i]=b[i];
}
signed main(){
#ifndef ONLINE_JUDGE
    freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
#endif // ONLINE_JUDGE
    scanf("%d%d",&s,&w);
    while(true){
        int op; scanf("%d",&op);
        if(op==3) break;
        if(op==1){
            int x,y,val; scanf("%d%d%d",&x,&y,&val);
            a[++cnt] = node{x,y,val,0};
        }else if(op==2){
            int x,y,xx,yy; scanf("%d%d%d%d",&x,&y,&xx,&yy);
            q[++tot]=cnt+1;
            ans[cnt+4] += (yy-y+1)*(xx-x+1)*s;
            a[++cnt]=node{x-1,y-1,cnt,1};
            a[++cnt]=node{x-1,yy,cnt,1};
            a[++cnt]=node{xx,y-1,cnt,1};
            a[++cnt]=node{xx,yy,cnt,1};
        }
    }
    CDQ(1,cnt);
    for(int i=1;i<=tot;i++)
        printf("%d\n",ans[q[i]+3]-ans[q[i]+2]-ans[q[i]+1]+ans[q[i]]);
    return 0;
}

发布了152 篇原创文章 · 获赞 1 · 访问量 2712

猜你喜欢

转载自blog.csdn.net/qq_43544481/article/details/103786358