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
",ans[i]);
76 }
View Code
原文地址:https://www.cnblogs.com/yyc-jack-0920/p/8067018.html