bzoj 1935 Tree 园丁的烦恼
题目大意:
一些点,每次查询一个矩形内有多少个点
思路:
因为空间太大
所以不能用什么二维树状数组
需要把这些点和所有查询的矩阵的左下和右上离线下来
先离散化
然后每个子矩阵像二维前缀和那样查询
按照x升序加入点,对于矩阵的点查询
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 2139062143 10 #define ll long long 11 #define MAXN 500100 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 17 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 int n,c[MAXN*3],vis[MAXN],m,cnt,k,ans[MAXN]; 21 struct data 22 { 23 int x,y,pos,yy; 24 }g[MAXN*3],a[MAXN*3]; 25 bool cmp1(data a,data b) 26 { 27 if(a.x<b.x) return 1; 28 if(a.x>b.x) return 0; 29 if(a.x==b.x) 30 { 31 if(a.pos<=n&&b.pos>n) return 1; 32 if(a.pos>n&&b.pos<=n) return 0; 33 return a.y<b.y; 34 } 35 } 36 bool cmp2(data a,data b) {return a.y<b.y||(a.y==b.y&&a.x<b.x);} 37 int lowbit(int x) {return x&(-x);} 38 void add(int x) {for(int i=x;i<=k;i+=lowbit(i)) c[i]++;} 39 int query(int x) {int res=0;for(int i=x;i;i-=lowbit(i)) res+=c[i];return res;} 40 int main() 41 { 42 n=read(),m=read(); 43 for(int i=1;i<=n;i++) 44 a[i].pos=g[i].pos=i,g[i].x=read(),g[i].y=read(); 45 for(int i=n+1;i<=n+2*m;i++) 46 a[i].pos=g[i].pos=i,g[i].x=read(),g[i].y=read(); 47 sort(g+1,g+n+2*m+1,cmp2); 48 g[0].x=g[0].y=-1,cnt=0; 49 //离散化--------------------------------------------------------- 50 for(int i=1;i<=n+2*m;i++) 51 { 52 if(g[i].y!=g[i-1].y) a[g[i].pos].y=++cnt; 53 else a[g[i].pos].y=cnt; 54 } 55 k=cnt+5;sort(g+1,g+n+2*m+1,cmp1);cnt=0; 56 for(int i=1;i<=n+2*m;i++) 57 { 58 if(g[i].x!=g[i-1].x) a[g[i].pos].x=++cnt; 59 else a[g[i].pos].x=cnt; 60 } 61 //对于每个子矩阵的点需要记录另一个点的纵坐标--------------------- 62 for(int i=1;i<=2*m;i+=2) 63 {--a[i+n].x,a[i+n].yy=a[i+1+n].y,a[i+1+n].yy=a[i+n].y;} 64 sort(a+1,a+n+m*2+1,cmp1); 65 for(int i=1;i<=n+2*m;i++) 66 { 67 if(a[i].pos>n)//如果是查询 68 { 69 int h=(a[i].pos-n+1)>>1;vis[h]++; 70 if(vis[h]==1) ans[h]=query(a[i].y-1)-query(a[i].yy);//左下角的点 71 if(vis[h]==2) ans[h]+=query(a[i].y)-query(a[i].yy-1);//右上角的点 72 } 73 else add(a[i].y);//不是查询的点 74 } 75 for(int i=1;i<=m;i++) printf("%d\n",ans[i]); 76 }