[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 }
View Code

 

posted @ 2018-07-22 17:11  Xu-daxia  阅读(217)  评论(0编辑  收藏  举报