luogu P4169 [Violet]天使玩偶/SJY摆棋子
题面传送门
考虑怎么把绝对值拆掉。
可以把坐标系旋转四次然后统计左上方的点,这样可以拆掉绝对值。那么就是要找左上方\(x+y\)最小的点,变成三维偏序问题。
可以用\(cdq\)分治轻松解决。
注意这道题卡常,可以尝试把\(cdq\)中的快排换成归并能快好几倍。
同时只对询问查询。
时间复杂度\(O(nlog^2n)\)常数很小。
代码实现:
#include<cstdio>
#include<algorithm>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
int n,m,k,xs,ys,zs,f[1000039],now;
struct yyy{int x,y,id,z,tim,w;}s[1000039],b[1000039];
inline bool cmp1(yyy x,yyy y){return x.x<y.x;}
inline bool cmp2(yyy x,yyy y){return x.tim<y.tim;}
inline void get(int x,int y){while(x<=zs) f[x]=max(f[x],y),x+=x&-x;}
inline int find(int x){int ans=0;while(x) ans=max(ans,f[x]),x-=x&-x;return ans;}
inline void clear(int x){while(x<=zs&&f[x]) f[x]=0,x+=x&-x;}
inline void slove(int x,int y){
if(x==y) return;
int m=x+y>>1,l=x,i,head=x-1;
slove(x,m);slove(m+1,y);
for(i=m+1;i<=y;i++){
//if(s[i].id==1) continue;
while(l<=m&&s[l].x<=s[i].x){
if(s[l].id==1)get(s[l].y,s[l].x+s[l].y);
b[++head]=s[l++];
}
if(s[i].id==2){
now=find(s[i].y);
if(now)s[i].w=min(s[i].w,s[i].x+s[i].y-now);
}b[++head]=s[i];
}
while(l<=m) b[++head]=s[l++];
for(i=x;i<l;i++) clear(s[i].y);
for(i=x;i<=y;i++) s[i]=b[i];
}
inline void read(int &x){
char s=getchar();x=0;
while(s<'0'||s>'9') s=getchar();
while(s>='0'&&s<='9') x=x*10+s-48,s=getchar();
}
inline void print(int x){
if(x>9) print(x/10);
putchar(x%10+48);
}
int main(){
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
register int i;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)read(s[i].x),read(s[i].y),s[i].x++,s[i].y++,s[i].id=1,s[i].tim=i,xs=max(xs,s[i].x),ys=max(ys,s[i].y);
for(i=n+1;i<=m+n;i++)read(s[i].id),read(s[i].x),read(s[i].y),s[i].x++,s[i].y++,s[i].w=1e9,s[i].tim=i,xs=max(xs,s[i].x),ys=max(ys,s[i].y);
zs=max(xs,ys)+2;n+=m;
slove(1,n);
sort(s+1,s+n+1,cmp2);
for(i=1;i<=n;i++) s[i].x=zs-s[i].x;
slove(1,n);
sort(s+1,s+n+1,cmp2);
for(i=1;i<=n;i++) s[i].y=zs-s[i].y;
slove(1,n);
sort(s+1,s+n+1,cmp2);
for(i=1;i<=n;i++) s[i].x=zs-s[i].x;
slove(1,n);
sort(s+1,s+n+1,cmp2);
for(i=1;i<=n;i++) if(s[i].id==2) print(s[i].w),putchar('\n');
}