您的位置:首页 > 其它

bzoj2683 简单题 (cdq分治 + 树状数组)

2017-11-26 12:11 399 查看

bzoj2683 简单题

原题地址http://www.lydsy.com/JudgeOnline/problem.php?id=2683

题意:

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

命令参数限制内容
1 x y A1<=x,y<=N,A是正整数将格子x,y里的数字加上A
2 x1 y1 x2 y21<=x1<= x2<=N,1<=y1<= y2<=N输出x1 y1 x2 y2这个矩形内的数字和
3终止程序
数据范围

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

题解:

内存20M,又因为N很大,上数据结构比较困难。

于是想到cdq分治。

对于一个查询(x1,y1,x2,y2)

我们把它分成四个查询 +(x1-1,y1-1),-(x1-1,y2), -(x2,y1-1) ,+(x2,y2),前缀和的加加减减。

这样只需考虑哪些操作会对我的查询有影响。

三个参数(x,y,time)

显然是三维都<=当前查询就会有影响,

这样就成了一个三维偏序问题,只不过树状数组里面存的,是带来的影响(加的数值)

于是cdq分治时用作半边的所有操作,去计算对右边所有询问的影响即可。

树状数组用了的才清。

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=500005;
const int M=1000005;
struct node
{
int typ,x,y,w,id; //类型,xy坐标,时刻, 影响(权值 或 +/-),ID
friend bool operator<(const node &A,const node &B)
{return (A.x!=B.x)? A.x<B.x:A.y<=B.y;}
}Q[M],R[M];
int n,tim=0,tail=0,qs=0,ans
;
struct B_I_T
{
int c
;
void add(int x,int val)
{
for(int i=x;i<=n;i=i+(i&(-i))) c[i]+=val;
}
int query(int x)
{
int ret=0;
for(int i=x;i>0;i=i-(i&(-i))) ret+=c[i];
return ret;
}
void clear(int x)
{
for(int i=x;i<=n;i=i+(i&(-i))) c[i]=0;
}
}Bit;
void cdq(int lf,int rg)
{
if(rg-lf<=0) return;
int mid=(lf+rg)>>1;
cdq(lf,mid); cdq(mid+1,rg);
int p1=lf; int p2=mid+1; int tail=lf-1;
while(p1<=mid&&p2<=rg)
{
if(Q[p1]<Q[p2])
{
if(Q[p1].typ==0) Bit.add(Q[p1].y,Q[p1].w);
R[++tail]=Q[p1++];
}
else
{
if(Q[p2].typ==1) ans[Q[p2].id]+=Q[p2].w*Bit.query(Q[p2].y);
R[++tail]=Q[p2++];
}

}
while(p1<=mid) R[++tail]=Q[p1++];
while(p2<=rg)
{
if(Q[p2].typ==1) ans[Q[p2].id]+=Q[p2].w*Bit.query(Q[p2].y);
R[++tail]=Q[p2++];
}
for(int i=lf;i<=rg;i++)
{
Bit.clear(R[i].y);
Q[i]=R[i];
}
}
int main()
{
scanf("%d",&n); n++;
while(1)
{
int opt;
scanf("%d",&opt);
if(opt==1)//1 x y A ,将格子x,y里的数字加上A
{
++tail; scanf("%d%d%d",&Q[tail].x,&Q[tail].y,&Q[tail].w);  Q[tail].x++; Q[tail].y++;
Q[tail].typ=0;
}
else if(opt==2)//2 x1 y1 x2 y2,输出x1 y1 x2 y2这个矩形内的数字和
{
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2); x1++; x2++; y1++; y2++;
qs++;
Q[++tail].typ=1; Q[tail].x=x1-1; Q[tail].y=y1-1; Q[tail].w=1;  Q[tail].id=qs;
Q[++tail].typ=1; Q[tail].x=x1-1; Q[tail].y=y2; Q[tail].w=-1; Q[tail].id=qs;
Q[++tail].typ=1; Q[tail].x=x2; Q[tail].y=y1-1; Q[tail].w=-1; Q[tail].id=qs;
Q[++tail].typ=1; Q[tail].x=x2; Q[tail].y=y2; Q[tail].w=1; Q[tail].id=qs;
}
if(opt==3) break;
}
cdq(1,tail);
for(int i=1;i<=qs;i++) printf("%d\n",ans[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: