Description
GFS打算去郊外建所别墅,享受生活,于是他耗费巨资买下了一块风水宝地,但令他震惊的是,一群DSJ对GFS的富贵生活深恶痛绝,决定打洞以搞破坏。
现在我们简化一下这个问题,在这片土地上会按顺序发生一系列事件。
①一只DSJ在(x,y) 这个点打了一个洞。
②有着高雅品味GFS想建一个等腰直角三角形的别墅,即由(x,y) ,(x+d,y) ,(x,y+d) 三点围成的三角形,但为了地基的牢固,他想知道当前这块三角形土地内的洞的个数。
GFS现在对DSJ已经忍无可忍了,请你帮他回答这些询问。
初始土地上没有洞。GFS毕竟是GFS,你可以认为土地无限大。
现在我们简化一下这个问题,在这片土地上会按顺序发生一系列事件。
①一只DSJ在(x,y) 这个点打了一个洞。
②有着高雅品味GFS想建一个等腰直角三角形的别墅,即由(x,y) ,(x+d,y) ,(x,y+d) 三点围成的三角形,但为了地基的牢固,他想知道当前这块三角形土地内的洞的个数。
GFS现在对DSJ已经忍无可忍了,请你帮他回答这些询问。
初始土地上没有洞。GFS毕竟是GFS,你可以认为土地无限大。
Input
第一行一个整数 n,表示事件数。接下来n行,每行3个非负整数x ,y ,d 。
若d=0 表示DSJ打洞的事件。否则表示GFS建房的询问。
若d=0 表示DSJ打洞的事件。否则表示GFS建房的询问。
Output
对每个询问输出一个整数,表示当时询问的三角形内的洞的个数。
Sample Input
输入1:
8
1 3 0
1 5 0
3 6 0
4 4 0
2 6 0
1 5 3
1 5 4
1 1 1
输入2:
4
1 5 0
3 7 0
2 5 6
2 3 4
Sample Output
输出1:
3
3
0
输出2:
1
0
Data Constraint
30%的数据n<=3333 。
另30% 的数据 GFS只会在DSJ打完洞后才开始询问,xi,yi<=333333 。
100%的数据 1<=n<=88888,xi,yi<=3333333 。
另30% 的数据 GFS只会在DSJ打完洞后才开始询问,xi,yi<=333333 。
100%的数据 1<=n<=88888,xi,yi<=3333333 。
题解
- 四维偏序问题,cdq分治,再用树状数组记录一个前缀和
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 using namespace std; 5 struct edge { int x,y,z,d; }a[900000],b[900000],c1[90000],c2[900000]; 6 int sz[40000000],ans[900000],tot,num,mx,n,x,y,d; 7 bool cmp(edge x,edge y) { return x.z<y.z||(x.z==y.z&&x.d<y.d); } 8 bool cmp1(edge x,edge y) { return x.x<=y.x; } 9 int lowbit(int x) { return x&-x; } 10 void insert(int x,int y) 11 { 12 num=num+y; 13 for (x;x<=mx;x+=lowbit(x)) sz[x]+=y; 14 } 15 int getsum(int x) 16 { 17 int k=num; 18 for (x;x;x-=lowbit(x)) k-=sz[x]; 19 return k; 20 } 21 void work(int l,int r) 22 { 23 if (l==r) return; 24 int mid=(l+r)/2,cnt1=0,cnt2=0; 25 work(l,mid),work(mid+1,r); 26 for (int i=l;i<=mid;i++) if (!b[i].d) c1[++cnt1]=b[i]; 27 for (int i=mid+1;i<=r;i++) if (b[i].d) c2[++cnt2]=b[i]; 28 if (!cnt1||!cnt2) return; 29 sort(c1+1,c1+cnt1+1,cmp1),sort(c2+1,c2+cnt2+1,cmp1); 30 int k=cnt1+1; 31 for (int i=cnt2;i>=1;i--) 32 { 33 while (k>1&&c1[k-1].x>=c2[i].x) insert(c1[--k].y,1); 34 ans[c2[i].d]+=getsum(c2[i].y-1); 35 } 36 for (int i=k;i<=cnt1;i++) insert(c1[i].y,-1); 37 } 38 void cdq(int l,int r) 39 { 40 if (l==r) return; 41 int mid=(l+r)/2; 42 cdq(l,mid),cdq(mid+1,r); 43 int cnt=0,boo=0; 44 for (int i=l;i<=mid;i++) if (!a[i].d) b[++cnt]=a[i]; 45 for (int i=mid+1;i<=r;i++) if (a[i].d) b[++cnt]=a[i],boo=1; 46 if (!boo||!cnt) return; 47 sort(b+1,b+cnt+1,cmp),work(1,cnt); 48 } 49 int main() 50 { 51 scanf("%d",&n); 52 for (int i=1;i<=n;i++) 53 { 54 scanf("%d%d%d",&x,&y,&d); 55 a[i].x=x+1,a[i].y=y+1,a[i].z=x+y+d,mx=max(mx,y+d); 56 if (d!=0) a[i].d=++tot; 57 } 58 cdq(1,n); 59 for (int i=1;i<=tot;i++) printf("%d\n",ans[i]); 60 }