BZOJ2716:[Violet 3]天使玩偶——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=2716
样例输入
2 3
1 1
2 3
2 1 2
1 3 3
2 4 2
样例输出
1
2
————————————————————————————————
整整一个上午的时间,终于DEBUG出来了,原来是因为我数组开小了……
首先我们很容易想到一个三元组(t,x,y),其中t为操作时间。
默认最开始给定的一些点的操作为插入,且时间优先级均高于其他的点。
那么显然就是三维偏序,CDQ可以上了。
给t排个序,边归并x边树状数组记录y,然后查即可……
但是我们怎么求dis啊?
我们有种玄学的方法叫做分情况讨论。
分成四种情况:
对于(x,y)(x1,y1)的dis:
x+y-(x1+y1) (x>x1,y>y1)
x-y-(x1-y1) (x>x1,y<y1)
-x+y-(y1-x1) (x<x1,y>y1)
-x-y-(-x1-y1) (x<x1,y<y1)
其中括号内的东西就是我们要用树状数组来维护的东西,显然当括号内的东西最大的时候我们的距离有最小值。
那么就变成了维护区间最大值的问题了,显然树状数组是能够胜任这项工作的。
具体的实现方法看我代码吧……不好描述。
#include<cstdio> #include<queue> #include<cctype> #include<cstring> #include<vector> #include<algorithm> using namespace std; typedef long long ll; const int M=500010; const int N=1000010; const int INF=10*N; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct rem{ int t; int x; int y; int pos; }q[2*M],tmp[2*M]; int m,n,cnt=0,ans[M],tree[N],maxy=-1; bool cmp(rem a,rem b){ return (a.t<b.t||(a.t==b.t&&a.x<b.x)||(a.t==b.t&&a.x==b.x&&a.y<b.y)||(a.t==b.t&&a.x==b.x&&a.y==b.y&&a.pos<b.pos)); } inline int lowbit(int t){return t&(-t);} void add(int x,int y){ for(int i=x;i<=maxy;i+=lowbit(i))tree[i]=max(tree[i],y); return; } int query(int x){ int res=-INF; for(int i=x;i>0;i-=lowbit(i))res=max(res,tree[i]); return res; } void cdq(int l,int r){ if(l>=r)return; int mid=(l+r)>>1; cdq(l,mid);cdq(mid+1,r); for(int i=l,j=l,p=mid+1;i<=r;i++){ if(j<=mid&&(p>r||q[j].x<=q[p].x))tmp[i]=q[j++]; else tmp[i]=q[p++]; } /////////// for(int i=l;i<=r;i++){ q[i]=tmp[i]; if(q[i].t<=mid&&!q[i].pos)add(q[i].y,q[i].x+q[i].y); if(q[i].t>mid&&q[i].pos)ans[q[i].pos]=min(ans[q[i].pos],q[i].x+q[i].y-query(q[i].y)); } for(int i=l;i<=r;i++){ if(q[i].t<=mid&&!q[i].pos){ for(int j=q[i].y;j<=maxy;j+=lowbit(j))tree[j]=-INF; } } /////////// for(int i=l;i<=r;i++){ if(q[i].t<=mid&&!q[i].pos)add(maxy-q[i].y,q[i].x-q[i].y); if(q[i].t>mid&&q[i].pos)ans[q[i].pos]=min(ans[q[i].pos],q[i].x-q[i].y-query(maxy-q[i].y)); } for(int i=l;i<=r;i++){ if(q[i].t<=mid&&!q[i].pos){ for(int j=maxy-q[i].y;j<=maxy;j+=lowbit(j))tree[j]=-INF; } } /////////// for(int i=r;i>=l;i--){ if(q[i].t<=mid&&!q[i].pos)add(q[i].y,q[i].y-q[i].x); if(q[i].t>mid&&q[i].pos)ans[q[i].pos]=min(ans[q[i].pos],-q[i].x+q[i].y-query(q[i].y)); } for(int i=l;i<=r;i++){ if(q[i].t<=mid&&!q[i].pos){ for(int j=q[i].y;j<=maxy;j+=lowbit(j))tree[j]=-INF; } } /////////// for(int i=r;i>=l;i--){ if(q[i].t<=mid&&!q[i].pos)add(maxy-q[i].y,-q[i].x-q[i].y); if(q[i].t>mid&&q[i].pos)ans[q[i].pos]=min(ans[q[i].pos],-q[i].x-q[i].y-query(maxy-q[i].y)); } for(int i=l;i<=r;i++){ if(q[i].t<=mid&&!q[i].pos){ for(int j=maxy-q[i].y;j<=maxy;j+=lowbit(j))tree[j]=-INF; } } /////////// return; } void clear(){ maxy++; for(int i=1;i<=cnt;i++)ans[i]=INF; for(int i=1;i<=maxy;i++)tree[i]=-INF; return; } int main(){ n=read(); m=read(); for(int i=1;i<=n;i++){ q[i].x=read()+1; q[i].y=read()+1; q[i].t=i; maxy=max(maxy,q[i].y); } for(int i=n+1;i<=m+n;i++){ int w=read(); if(w==1){ q[i].x=read()+1; q[i].y=read()+1; q[i].t=i; maxy=max(maxy,q[i].y); }else{ q[i].x=read()+1; q[i].y=read()+1; q[i].t=i; q[i].pos=++cnt; maxy=max(maxy,q[i].y); } } sort(q+1,q+m+n+1,cmp); clear(); cdq(1,m+n); for(int i=1;i<=cnt;i++)printf("%d\n",ans[i]); return 0; }