[bzoj1807] [Ioi2007]Pairs 彼此能听得见的动物对数
这题挺神的...膜了半天claris的题解还有官方题解。。
一维随便搞,
二维的话就旋转坐标系,把原来的点(x,y)变成(x+y,x-y),把曼哈顿距离变成切比雪夫距离。然后排序后扫描线,树状数组维护。
三维的话.....官方题解是旋转坐标系后直接三维树状数组?(吓哭
Claris的题解说只要旋转后两维,预处理一波前缀和就行了....具体推一下就知道了。
三维官方题解复杂度是nlog^3n,Claris做法是nm。。劲啊
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #define ll long long 6 using namespace std; 7 const int maxn=100233; 8 int x[maxn]; 9 struct zs{int x,y,z;}a[maxn]; 10 ll ans; 11 int i,j,k,n,m,D,id,M; 12 13 bool cmp(zs a,zs b){return a.x<b.x;} 14 int ra;char rx; 15 inline int read(){ 16 rx=getchar(),ra=0; 17 while(rx<'0'||rx>'9')rx=getchar(); 18 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 19 } 20 21 inline void run1(){ 22 register int i,l=1; 23 for(i=1;i<=n;i++)x[i]=read(); 24 sort(x+1,x+1+n); 25 for(i=2;i<=n;ans+=i-l,i++)while(x[i]-x[l]>D)l++; 26 } 27 28 int t[75233<<1]; 29 inline void del(int x){while(x<=M)t[x]--,x+=x&-x;} 30 inline void add(int x){while(x<=M)t[x]++,x+=x&-x;} 31 inline ll query(int x){ 32 if(x<=0)return 0; 33 if(x>M)x=M; 34 ll sm=0; 35 while(x)sm+=t[x],x-=x&-x; 36 return sm; 37 } 38 inline void run2(){ 39 register int i; 40 for(i=1;i<=n;i++)j=read(),k=read(),a[i].x=j+k,a[i].y=j-k+m; 41 sort(a+1,a+1+n,cmp);int top=1; 42 for(i=1;i<=n;i++){ 43 while(a[top].x+D<a[i].x)del(a[top].y),top++; 44 ans+=query(a[i].y+D)-query(a[i].y-D-1), 45 add(a[i].y); 46 } 47 } 48 49 ll mp[77][77<<1][77<<1]; 50 inline ll getsm(int x,int x1,int y1,int x2,int y2){ 51 if(x1<1)x1=1;if(y1<1)y1=1; 52 if(x2>M)x2=M;if(y2>M)y2=M; 53 return mp[x][x2][y2]-mp[x][x1-1][y2]-mp[x][x2][y1-1]+mp[x][x1-1][y1-1]; 54 } 55 inline void run3(){ 56 register int i,j,k;int x;ll tmp=0; 57 for(i=1;i<=n;i++)a[i].x=read(),j=read(),k=read(),a[i].y=j+k,a[i].z=j-k+m; 58 sort(a+1,a+1+n,cmp); 59 for(i=1;i<=n;){ 60 x=a[i].x; 61 for(j=i;a[j+1].x==x;j++); 62 while(i<=j)mp[x][a[i].y][a[i].z]++,i++; 63 for(j=1;j<=M;j++)for(k=1;k<=M;k++)mp[x][j][k]+=mp[x][j-1][k]+mp[x][j][k-1]-mp[x][j-1][k-1]; 64 } 65 for(i=1;i<=n;i++){ 66 for(j=a[i].x+1;j<=m&&j-a[i].x<=D;j++) 67 k=D-(j-a[i].x),ans+=getsm(j,a[i].y-k,a[i].z-k,a[i].y+k,a[i].z+k); 68 tmp+=getsm(a[i].x,a[i].y-D,a[i].z-D,a[i].y+D,a[i].z+D)-1; 69 } 70 tmp>>=1; 71 ans+=tmp; 72 } 73 int main(){ 74 id=read(),n=read(),D=read(),m=read();M=m<<1; 75 if(D>=m*id){printf("%lld\n",(ll)n*(n-1)/2);} 76 if(id==1)run1(); 77 if(id==2)run2(); 78 if(id==3)run3(); 79 printf("%lld\n",ans); 80 return 0; 81 }