bzoj 2683: 简单题

2683: 简单题

Time Limit: 50 Sec  Memory Limit: 128 MB
Submit: 1779  Solved: 720
[Submit][Status][Discuss]

Description

你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:

 

命令

参数限制

内容

1 x y A

1<=x,y<=N,A是正整数

将格子x,y里的数字加上A

2 x1 y1 x2 y2

1<=x1<= x2<=N

1<=y1<= y2<=N

输出x1 y1 x2 y2这个矩形内的数字和

3

终止程序

Input

输入文件第一行一个正整数N。
接下来每行一个操作。
 

Output

对于每个2操作,输出一个对应的答案。
 

Sample Input

4
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3

Sample Output

3
5

HINT

 

1<=N<=500000,操作数不超过200000个,内存限制20M。

对于100%的数据,操作1中的A不超过2000。
/*
    CDQ分治。
    用CDQ分治做了线段树练习之后感觉大体脉络了解了一点,再做这个题,发现基本思路是一样的,就是会出现其他算法的插入,比如说加一点数据结构维护多维什么的。
    这个题用了树状数组,注意树状数组的插入和询问是在哪个位置使用的
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#define maxn 800010
using namespace std;
int n,tot,T,ans[maxn],tr[maxn];
struct node{
    int t;//第几次操作 
    int x,y;//操作的位置 
    int z;//增加量
    int belong;//属于哪次查询 
    int op;//操作类型 
    bool operator < (const node & q1)const{
        if(x!=q1.x)return x<q1.x;
        if(y!=q1.y)return y<q1.y;
        return op<q1.op;
    }
}q[maxn],tmp[maxn];
void modify(int x,int v){
    while(x<=n){
        tr[x]+=v;
        x+=x&(-x);
    }
}
int query(int x){
    int sum=0;
    while(x){
        sum+=tr[x];
        x-=x&(-x);
    }
    return sum;
}
void work(int l,int r){
    if(l==r)return;
    int mid=(l+r)>>1;
    for(int i=l;i<=r;i++){
        if(q[i].t<=mid&&q[i].op==1)modify(q[i].y,q[i].z);
        if(q[i].t>mid&&q[i].op==2)
            ans[q[i].belong]+=query(q[i].y)*q[i].z;
    }
    for(int i=l;i<=r;i++)
        if(q[i].t<=mid&&q[i].op==1)modify(q[i].y,-q[i].z);//进行恢复操作 
    int l1=l,l2=mid+1;
    for(int i=l;i<=r;i++){
        if(q[i].t<=mid)tmp[l1++]=q[i];
        else tmp[l2++]=q[i];
    }
    for(int i=l;i<=r;i++)q[i]=tmp[i];
    work(l,mid);work(mid+1,r);
}
int main(){
    freopen("Cola.txt","r",stdin);
    scanf("%d",&n);
    int opt,x1,y1,x2,y2,x,y,z;
    while(1){
        scanf("%d",&opt);
        if(opt==3)break;
        if(opt==1){
            scanf("%d%d%d",&x,&y,&z);
            q[++tot].x=x;q[tot].y=y;q[tot].t=tot;q[tot].op=1;q[tot].z=z;
        }
        if(opt==2){
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            q[++tot].x=x1-1;q[tot].y=y1-1;q[tot].t=tot;q[tot].op=2;q[tot].z=1;q[tot].belong=++T;
            q[++tot].x=x1-1;q[tot].y=y2;q[tot].t=tot;q[tot].op=2;q[tot].z=-1;q[tot].belong=T;
            q[++tot].x=x2;q[tot].y=y1-1;q[tot].t=tot;q[tot].op=2;q[tot].z=-1;q[tot].belong=T;
            q[++tot].x=x2;q[tot].y=y2;q[tot].t=tot;q[tot].op=2;q[tot].z=1;q[tot].belong=T;
        }
    }
    sort(q+1,q+tot+1);
    work(1,tot);
    for(int i=1;i<=T;i++)printf("%d\n",ans[i]);
    return 0;
}

 

posted @ 2017-12-21 16:11  Echo宝贝儿  阅读(152)  评论(0编辑  收藏  举报