bzoj1807: [Ioi2007]Pairs 彼此能听得见的动物对数
很有趣的一道题233
一维送分的,排序后弄个指针扫描维护当前最远能够听见的位置即可
二维我会肝两次分治,后来看claris博客发现可以把曼哈顿距离换成切比雪夫距离,要满足|xi-xj|<=D&&|yi-yj|<=D
这样就好做了,转化成区间问题扫描线+线段树水
三维不管高,然后同样的转换,因为m很小对于每个动物都可以枚举去第几层,用二维前缀和出解即可
然而卡空间卡空间边界超久。。。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #define mp(k,i,j) mp[k][i][j+105] using namespace std; typedef long long LL; int n,D,m,c[110000]; void solve1() { scanf("%d%d%d",&n,&D,&m); for(int i=1;i<=n;i++)scanf("%d",&c[i]); sort(c+1,c+n+1); int r=0;LL ans=0; for(int l=1;l<=n;l++) { while(r<n&&c[r+1]-c[l]<=D)r++; ans+=r-l; } printf("%lld\n",ans); } //-------------------------------------------------------------------------------- int s[210000]; int lowbit(int x){return x&-x;} void change(int x,int k) { while(x<=n) { s[x]+=k; x+=lowbit(x); } } int getsum(int x) { int ret=0; while(x>0) { ret+=s[x]; x-=lowbit(x); } return ret; } struct node2{int x,y;}p[110000]; int lslen,ls[110000]; bool node2_cmp(node2 n1,node2 n2){return n1.x<n2.x;} int LB(int x){return lower_bound(ls+1,ls+lslen+1,x)-ls;} int UB(int x){return upper_bound(ls+1,ls+lslen+1,x)-ls;} struct line { int op,x,y; line(){} line(int OP,int X,int Y){op=OP;x=X;y=Y;} }li[310000];int lilen; bool line_cmp(line l1,line l2){return l1.x==l2.x?l1.op<l2.op:l1.x<l2.x;} void solve2() { scanf("%d%d%d",&n,&D,&m);lilen=0; for(int i=1;i<=n;i++) { scanf("%d%d",&p[i].x,&p[i].y),p[i].x*=2,p[i].y*=2; int xx=(p[i].x+p[i].y)/2,yy=(p[i].x-p[i].y)/2; p[i].x=xx,p[i].y=yy; ls[++lslen]=yy; li[++lilen]=line(0,p[i].x-D,p[i].y); li[++lilen]=line(1,p[i].x,p[i].y); li[++lilen]=line(2,p[i].x+D,p[i].y); } sort(ls+1,ls+lslen+1); lslen=unique(ls+1,ls+lslen+1)-ls-1; sort(li+1,li+lilen+1,line_cmp); LL ans=0; memset(s,0,sizeof(s)); for(int i=1;i<=lilen;i++) { if(li[i].op==0)change(LB(li[i].y),1); else if(li[i].op==1)ans+=getsum(UB(li[i].y+D)-1)-getsum(LB(li[i].y-D)-1)-1; else change(LB(li[i].y),-1); } printf("%lld\n",ans/2); } //-------------------------------------------------------------------------------- struct node3{int x,y,z;}o[210000]; int mp[80][210][210]; void solve3() { int x,y,z; scanf("%d%d%d",&n,&D,&m); memset(mp,0,sizeof(mp)); for(int i=1;i<=n;i++) { scanf("%d%d%d",&o[i].x,&o[i].y,&o[i].z),o[i].x*=2,o[i].y*=2; int xx=(o[i].x+o[i].y)/2,yy=(o[i].x-o[i].y)/2; o[i].x=xx,o[i].y=yy; mp(o[i].z,o[i].x,o[i].y)++; } for(int k=1;k<=m;k++) for(int i=1;i<=200;i++) for(int j=-100;j<=100;j++) mp(k,i,j)+=mp(k,i-1,j)+mp(k,i,j-1)-mp(k,i-1,j-1); LL ans=0; for(int i=1;i<=n;i++) { for(int k=1;k<=m;k++) { int W=D-abs(o[i].z-k);if(W<0)continue; ans+=mp(k,min(200,o[i].x+W),min(100,o[i].y+W)) -mp(k,min(200,o[i].x+W),max(-100,o[i].y-W-1)) -mp(k,max(0,o[i].x-W-1),min(100,o[i].y+W)) +mp(k,max(0,o[i].x-W-1),max(-100,o[i].y-W-1)); } ans--; } printf("%lld\n",ans/2); } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int B; scanf("%d",&B); if(B==1)solve1(); else if(B==2)solve2(); else solve3(); return 0; }
pain and happy in the cruel world.