BZOJ#2683. 简单题

2683: 简单题

Time Limit: 50 Sec  Memory Limit: 128 MB
Submit: 2091  Solved: 847

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裸题

我们可以很方便求出一个前缀面积,就是(0,0)(x,y)的面积,我们只需要按时间排序,在里面再按x排序,y加入树状数组
找到time>time[i],x>=x[i],y>=y[i]即可
那么我们怎么求(x,y)(c,d)的矩形呢?
我们可以把它拆成4个矩形(0,0)(x-1,y-1),(0,0)(x-1,d),(0,0)(c,d),(0,0)(c,y-1)
合并一下就可以了

 


 

附上代码:
//CDQ把每个查询矩形划分为4部分 每部分可以单独求出
//求出的方法是找到x1<x2,y1<y2,时间在他出现之前
//合并答案 
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+12;
const int M=8e5+12;
struct date
{
    int type,x,y,v,id;
}d[M];
int n,m,cnt,c[N],pos[M],ans[M];

int cmp(date a,date b)
{
    return a.x<b.x;
}

inline int lowbit(int x) {return x&(-x);}
void add(int a,int b)
{
    while(a<=n) 
    {
        c[a]+=b;
        a+=lowbit(a);
    }
}
int sum(int a)
{
    int s=0;
    while(a)
    {
        s+=c[a];
        a-=lowbit(a);
    }
    return s;
}

void CDQ(int l,int r)
{
    if(l==r) return ;
    int mid=(l+r)>>1,temp=0;
    CDQ(l,mid);CDQ(mid+1,r);
    sort(d+l,d+mid+1,cmp);sort(d+mid+1,d+r+1,cmp);
    int i=l,j=mid+1;
    while(j<=r)
    {
        while(d[i].type==2&&i<=mid) i++;
        while(d[j].type==1&&j<=r) j++;
        if(i<=mid&&d[i].x<=d[j].x) add(d[i].y,d[i].v),i++,temp=i-1;
        else if(j<=r) ans[d[j].id]+=sum(d[j].y),j++;
    }
    for(int i=l;i<=temp;i++) if(d[i].type==1) add(d[i].y,-d[i].v);
}

int main()
{
    freopen("a.in","r",stdin);
    int type,x1,x2,y1,y2;
    scanf("%d",&n);
    while(1)
    {
        scanf("%d",&type);
        if(type==3) break;
        if(type==1)
        {
            d[++m].type=type;d[m].id=m;
            scanf("%d%d%d",&d[m].x,&d[m].y,&d[m].v);
        }
        else 
        {
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            pos[++cnt]=m;
            d[++m].type=type;d[m].x=x1-1;d[m].y=y1-1;d[m].id=m;
            d[++m].type=type;d[m].x=x2;d[m].y=y2;d[m].id=m;
            d[++m].type=type;d[m].x=x1-1;d[m].y=y2;d[m].id=m;
            d[++m].type=type;d[m].x=x2;d[m].y=y1-1;d[m].id=m;
        }
    }
    CDQ(1,m);
    for(int i=1;i<=cnt;i++) printf("%d\n",ans[pos[i]+1]+ans[pos[i]+2]-ans[pos[i]+3]-ans[pos[i]+4]);
    return 0;
}
View Code

 


 

posted @ 2018-05-08 07:53  Heey  阅读(156)  评论(0编辑  收藏  举报