[BZOJ2716][Violet 3]天使玩偶(cdq分治+bit)
2017-01-08 17:40
399 查看
题目描述
传送门题解
上下左右想想就不好搞啊…所以我们每一次只统计某个点左下方与它最近的,然后做4遍|x-x’|+|y-y’|=(x+y)-(x’+y’),也就是求x+y最大的点
然后这不就和三维偏序问题差不多了么?
按照时间排序分治,每一次对(l,mid)和(mid+1,r)按照x排序,然后两个指针,对于每一个询问将横坐标都小于等于它的点按照y加入bit,权值为x+y,查询最大值
然而写完了之后狂T不止啊…这一波常数卡得
首先归并排序的方法确实要快很多
然后就是学了一点hxy的姿势:只有询问才加点,不是询问就不加,也就是能不做的就不做
sort慢
代码
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<ctime> using namespace std; #define N 1000005 int n,m,opt,acnt,bcnt,pa,pb,tot,inf,INF; int ans ,ch ; struct hp{int x,y,id;bool flag;}p ,q ; int C ; int read() { int x=0;char c=getchar(); while (c<'0'||c>'9') c=getchar(); while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); return x; } void add(int loc,int val) { if (!loc) return; for (int i=loc;i<=inf;i+=i&(-i)) C[i]=max(C[i],val); } void cover(int loc) { if (!loc) return; for (int i=loc;i<=inf;i+=i&(-i)) C[i]=-1; } int query(int loc) { int ans=-1; for (int i=loc;i>=1;i-=i&(-i)) ans=max(ans,C[i]); return ans; } void cdq(int l,int r) { if (l>=r) return; int mid=(l+r)>>1; pa=l,pb=mid+1; for (int i=l;i<=r;++i) if (p[i].id<=mid) q[pa++]=p[i]; else q[pb++]=p[i]; for (int i=l;i<=r;++i) p[i]=q[i]; pa=l,pb=mid+1;tot=0; while (pb<=r) { if (p[pb].flag) { while (pa<=mid&&p[pa].x<=p[pb].x) { if(!p[pa].flag)add(p[pa].y,p[pa].x+p[pa].y); ch[++tot]=p[pa].y; ++pa; } int t=query(p[pb].y); if(t!=-1)ans[p[pb].id]=min(ans[p[pb].id],p[pb].x+p[pb].y-t); } ++pb; } for (int i=1;i<=tot;++i)cover(ch[i]); cdq(l,mid); cdq(mid+1,r); } int cmp(hp a,hp b){return a.x<b.x;} int main() { n=read();m=read(); for (int i=1;i<=n;++i) { p[i].x=read();p[i].y=read(); p[i].id=i; inf=max(inf,p[i].x);inf=max(inf,p[i].y); } m+=n; for (int i=n+1;i<=m;++i) { opt=read(); if(opt==2)p[i].flag=1; p[i].x=read();p[i].y=read(); p[i].id=i; inf=max(inf,p[i].x);inf=max(inf,p[i].y); } memset(ans,127,sizeof(ans));INF=ans[0]; memset(C,-1,sizeof(C)); sort(p+1,p+m+1,cmp);cdq(1,m); for (int i=1;i<=m;++i)p[i].y=inf-p[i].y+1;sort(p+1,p+m+1,cmp);cdq(1,m); for (int i=1;i<=m;++i)p[i].x=inf-p[i].x+1;sort(p+1,p+m+1,cmp);cdq(1,m); for (int i=1;i<=m;++i)p[i].y=inf-p[i].y+1;sort(p+1,p+m+1,cmp);cdq(1,m); for (int i=n+1;i<=m;++i) if (ans[i]!=INF) printf("%d\n",ans[i]); }
总结
①卡常数技巧:能不做的就不做。相关文章推荐
- BZOJ 2716 [Violet 3]天使玩偶 ——KD-Tree
- bzoj2716 [Violet 3]天使玩偶 k-d树
- BZOJ 2648: SJY摆棋子/BZOJ 2716: [Violet 3]天使玩偶 kdtree
- BZOJ2716:[Violet 3]天使玩偶——题解
- [KDTree] [BZOJ2716] [Violet 3] 天使玩偶
- 【BZOJ 2716/2648】 [Violet 3]天使玩偶 SJY摆棋子
- BZOJ 2648 SJY摆棋子 / 2716 Violet 3 天使玩偶 K-D树
- BZOJ.2716.[Violet3]天使玩偶(K-D Tree)
- 【Violet3】【BZOJ2716】天使玩偶
- BZOJ 2716: [Violet 3]天使玩偶 [CDQ分治]
- bzoj2716 [Violet 3]天使玩偶(同bzoj2648)
- BZOJ2716 [Violet 3]天使玩偶 【CDQ分治】
- 【bzoj 2716】[Violet 3]天使玩偶 (cdq分治+树状数组)
- BZOJ 2716 Violet 3 天使玩偶 CDQ分治
- BZOJ 2716 Violet 3 天使玩偶 CDQ分治
- BZOJ 2716 [Violet 3]天使玩偶
- 【BZOJ】2648: SJY摆棋子 & 2716: [Violet 3]天使玩偶(kdtree)
- BZOJ2716 [Violet]天使玩偶(cdq分治+树状数组)
- BZOJ 2716: [Violet 3]天使玩偶( CDQ分治 + 树状数组 )
- BZOJ 2716: [Violet 3]天使玩偶 | CDQ分治