[BZOJ1935][SHOI2007]Tree 园丁的烦恼(离线+树状数组)
题意
给出第一象限的n个点,有m次询问,每次询问一个矩形中的点的个数.(0<=n,m<=500000,0<=xi,yi<=10000000)
题解
一眼望去不可做。
用二位前缀和的思想,一个矩形可以用以坐标轴为一对临边的四个矩形加减得到。
考虑离线,离散化。所以我们要求的只是若干个以坐标轴为一对临边的矩形的权值。
但还是不可做。
转化为序列问题,我们要求的矩形面积,其实就是每行前缀和的一段连续地和。
具体一些,就是,算出每一行的前缀和,对于横坐标相等的前缀和,我们维护他们,矩形的面积,就是这些前缀和的前面一段。同时维护一个横坐标指针x,在x右移时前缀和加上横坐标为x的点。我们发现这些操作可以用树状数组维护。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 using namespace std; 7 int const N=7001000; 8 int head[N],hed[N],c[N],n,m; 9 int cnt,cntx,cnty,totx,toty,ans[N],tot,x[N],y[N]; 10 struct zb{ 11 int x,y; 12 }zb[N]; 13 struct ask{ 14 int x,xx,y,yy; 15 }q[N]; 16 struct edge{ 17 int to,nxt; 18 }e[N]; 19 struct hhh{ 20 int to,nxt,w,id; 21 }f[N]; 22 void add(int u,int v){ 23 cnt++; 24 e[cnt].nxt=head[u]; 25 e[cnt].to=v; 26 head[u]=cnt; 27 } 28 void ad(int u,int v,int c,int x){ 29 tot++; 30 f[tot].nxt=hed[u]; 31 f[tot].w=c; 32 f[tot].to=v; 33 f[tot].id=x; 34 hed[u]=tot; 35 } 36 int lowbit(int x){ 37 return x&-x; 38 } 39 void update(int x,int w){ 40 for(int i=x;i<=cnty;i+=lowbit(i)){ 41 c[i]+=1; 42 } 43 } 44 int check(int x,int w){ 45 if(x==0)return 0; 46 int ans=0; 47 for(int i=x;i>=1;i-=lowbit(i)){ 48 ans+=c[i]; 49 } 50 return ans*w; 51 } 52 void work(){ 53 for(int i=1;i<=cntx;i++){ 54 for(int j=head[i];j;j=e[j].nxt){ 55 int v=e[j].to; 56 update(v,1); 57 } 58 for(int j=hed[i];j;j=f[j].nxt){ 59 int v=f[j].to; 60 ans[f[j].id]+=check(v,f[j].w); 61 } 62 } 63 } 64 int main(){ 65 scanf("%d%d",&n,&m); 66 for(int i=1;i<=n;i++){ 67 scanf("%d%d",&zb[i].x,&zb[i].y); 68 x[++totx]=zb[i].x; 69 y[++toty]=zb[i].y; 70 } 71 for(int i=1;i<=m;i++){ 72 scanf("%d%d%d%d",&q[i].x,&q[i].y,&q[i].xx,&q[i].yy); 73 x[++totx]=q[i].x; 74 y[++toty]=q[i].y; 75 x[++totx]=q[i].xx; 76 y[++toty]=q[i].yy; 77 } 78 sort(x+1,x+1+totx); 79 sort(y+1,y+1+toty); 80 cntx=unique(x+1,x+1+totx)-(x+1); 81 cnty=unique(y+1,y+1+toty)-(y+1); 82 for(int i=1;i<=n;i++){ 83 zb[i].x=lower_bound(x+1,x+1+cntx,zb[i].x)-x; 84 zb[i].y=lower_bound(y+1,y+1+cnty,zb[i].y)-y; 85 add(zb[i].x,zb[i].y); 86 } 87 for(int i=1;i<=m;i++){ 88 q[i].x=lower_bound(x+1,x+1+cntx,q[i].x)-x; 89 q[i].y=lower_bound(y+1,y+1+cnty,q[i].y)-y; 90 q[i].xx=lower_bound(x+1,x+1+cntx,q[i].xx)-x; 91 q[i].yy=lower_bound(y+1,y+1+cnty,q[i].yy)-y; 92 ad(q[i].x-1,q[i].y-1,1,i); 93 ad(q[i].xx,q[i].yy,1,i); 94 ad(q[i].x-1,q[i].yy,-1,i); 95 ad(q[i].xx,q[i].y-1,-1,i); 96 } 97 work(); 98 for(int i=1;i<=m;i++){ 99 printf("%d\n",ans[i]); 100 } 101 return 0; 102 }