[bzoj] 2716 天使玩偶 || CDQ分治
2017-12-18 15:33
381 查看
原题
已知n个点有天使玩偶,有m次操作:
操作1:想起来某个位置有一个天使玩偶
操作2:询问离当前点最近的天使玩偶的曼哈顿距离
显然的CDQ问题,三维分别为时间,x轴,y轴。
但是这道题的问题在于最近距离怎么维护。
曼哈顿距离定义为|x2-x1|+|y2-y1|,所以把绝对值展开后一共有四种情况:
\(x2-x1+y2-y1 => x2+y2-(x1+y1) x1-x2+y2-y1 => -x2+y2+(x1-y1) x2-x1+y1-y2 => x2-y2+(y1-x1) x1-x2+y1-y2 => -x2-y2+(x1+y1)\)
所以把四种情况都讨论一遍,每次处理为该情况的点对即可。
#include<cstdio> #include<algorithm> #include<cstring> #define N 500010 using namespace std; int n,m,op,ans ,mxy,f[1000010]; struct hhh { int x,y,tm,op,num; bool operator < (const hhh &b) const { return tm<b.tm; } }p[2*N],tmp[2*N]; int read() { int ans=0,fu=1; char j=getchar(); for (;j<'0' || j>'9';j=getchar()) if (j=='-') fu=-1; for (;j>='0' && j<='9';j=getchar()) ans*=10,ans+=j-'0'; return ans*fu; } inline void add(int x,int y) { while (x<=mxy) f[x]=max(f[x],y),x+=x&-x; } inline int query(int x) { int ans=0xc0c0c0c0; while (x) ans=max(ans,f[x]),x-=x&-x; return ans; } inline void clear(int x) { while (x<=mxy) f[x]=0xc0c0c0c0,x+=x&-x; } void solve(int l,int r) { if (l==r) return ; int mid=(l+r)>>1; solve(l,mid); solve(mid+1,r); int l1=l,l2=mid+1; for (int i=l;i<=r;i++) { if (l1<=mid && (l2>r || p[l1].x<p[l2].x)) tmp[i]=p[l1++]; else tmp[i]=p[l2++]; } for (int i=l;i<=r;i++) { p[i]=tmp[i]; if (p[i].tm>mid && p[i].op) ans[p[i].num]=min(ans[p[i].num],p[i].x+p[i].y-query(p[i].y)); if (p[i].tm<=mid && !p[i].op) add(p[i].y,p[i].x+p[i].y); } for (int i=l;i<=r;i++) { if (p[i].tm<=mid && !p[i].op) clear(p[i].y); } for (int i=l;i<=r;i++) { if (p[i].tm>mid && p[i].op) ans[p[i].num]=min(ans[p[i].num],p[i].x-p[i].y-query(mxy-p[i].y)); if (p[i].tm<=mid && !p[i].op) add(mxy-p[i].y,p[i].x-p[i].y); } for (int i=l;i<=r;i++) { if (p[i].tm<=mid && !p[i].op) clear(mxy-p[i].y); } for (int i=r;i>=l;i--) { if (p[i].tm>mid && p[i].op) ans[p[i].num]=min(ans[p[i].num],-p[i].x+p[i].y-query(p[i].y)); if (p[i].tm<=mid && !p[i].op) add(p[i].y,p[i].y-p[i].x); } for (int i=r;i>=l;i--) { if (p[i].tm<=mid && !p[i].op) clear(p[i].y); } for (int i=r;i>=l;i--) { if (p[i].tm>mid && p[i].op) ans[p[i].num]=min(ans[p[i].num],-p[i].x-p[i].y-query(mxy-p[i].y)); if (p[i].tm<=mid && !p[i].op) add(mxy-p[i].y,-p[i].x-p[i].y); } for (int i=r;i>=l;i--) { if (p[i].tm<=mid && !p[i].op) clear(mxy-p[i].y); } } int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); n=read(); m=read(); for (int i=1;i<=n;i++) { p[i].x=read()+1; p[i].y=read()+1; p[i].tm=i; mxy=max(mxy,p[i].y); } for (int i=1;i<=m;i++) { op=read(); p[n+i].x=read()+1; p[n+i].y=read()+1; p[n+i].tm=n+i; mxy=max(mxy,p[n+i].y); if (op==2) p[n+i].num=++ans[0],p[n+i].op=1; } for (int i=1;i<=ans[0];i++) ans[i]=0x3f3f3f3f; mxy++; for (int i=0;i<=mxy;i++) f[i]=0xc0c0c0c0; sort(p+1,p+n+m+1); solve(1,n+m); for (int i=1;i<=ans[0];i++) printf("%d\n",ans[i]); return 0; }
相关文章推荐
- BZOJ.2716.[Violet3]天使玩偶(CDQ分治 坐标变换)
- bzoj 2716 [Violet 3]天使玩偶 【CDQ分治】
- [BZOJ2716][Violet 3]天使玩偶(cdq分治||KD-tree)
- BZOJ 2716: [Violet 3]天使玩偶 [CDQ分治]
- bzoj 2716: [Violet 3]天使玩偶(cdq分治)
- bzoj2716 [Violet 3]天使玩偶(CDQ分治)
- BZOJ 2716 Violet 3 天使玩偶 CDQ分治
- BZOJ2716 [Violet 3]天使玩偶 【CDQ分治】
- [BZOJ2716][天使玩偶angel][CDQ分治]
- BZOJ 2716: [Violet 3]天使玩偶( CDQ分治 + 树状数组 )
- BZOJ 2716 Violet 3 天使玩偶 CDQ分治
- bzoj 2716 天使玩偶(CDQ分治,BIT)
- BZOJ 2716: [Violet 3]天使玩偶 | CDQ分治
- BZOJ 2716 [Violet 3]天使玩偶
- 【bzoj 2716】[Violet 3]天使玩偶 (cdq分治+树状数组)
- BZOJ2716:[Violet 3]天使玩偶——题解
- [BZOJ]2716: [Violet 3]天使玩偶 CDQ分治+树状数组
- bzoj 2648: SJY摆棋子&&2716: [Violet 3]天使玩偶 --kdtree
- 【BZOJ】2648: SJY摆棋子 & 2716: [Violet 3]天使玩偶(kdtree)
- bzoj2716: [Violet 3]天使玩偶