BZOJ2716: [Violet 3]天使玩偶
题解: 通过取绝对值考虑后 发现是一个较复杂的cdq 突然考虑距离问题 用Kdtree写也是可行的 但是.....会退化 所以我们考虑用替罪羊树来防止退化
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <stack> #include <queue> #include <cmath> #include <set> #include <map> #define mp make_pair #define pb push_back #define pii pair<int,int> #define link(x) for(edge *j=h[x];j;j=j->next) #define inc(i,l,r) for(int i=l;i<=r;i++) #define dec(i,r,l) for(int i=r;i>=l;i--) const int MAXN=5e5+10; const double eps=1e-8; #define ll long long const int inf=1e9+7; #define alpha 0.75 using namespace std; struct edge{int t,v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e; void add(int x,int y,int vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;} ll read(){ ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x*f; } int d,rt; typedef struct node{ int p[2],maxx[2],minn[2],c[2],sz; friend bool operator<(node aa,node bb){ if(aa.p[d]==bb.p[d])return aa.p[d^1]<bb.p[d^1]; return aa.p[d]<bb.p[d]; } }node; node a[MAXN<<1]; int St[MAXN],tot,n,m,tot1; node st[MAXN<<1]; int newnode(int t){ int x=St[tot--]; a[x].sz=1; inc(i,0,1)a[x].p[i]=a[x].maxx[i]=a[x].minn[i]=st[t].p[i],a[x].c[i]=0; return x; } void up(int x,int y){ if(!x||!y)return ; inc(i,0,1)a[x].maxx[i]=max(a[x].maxx[i],a[y].maxx[i]),a[x].minn[i]=min(a[x].minn[i],a[y].minn[i]); } int built(int l,int r,int now){ int mid=(l+r)>>1; d=now;nth_element(a+l,a+mid,a+r+1); inc(i,0,1)a[mid].maxx[i]=a[mid].minn[i]=a[mid].p[i]; a[mid].c[0]=a[mid].c[1]=0;a[mid].sz=1; if(l<mid)a[mid].c[0]=built(l,mid-1,now^1),up(mid,a[mid].c[0]); if(r>mid)a[mid].c[1]=built(mid+1,r,now^1),up(mid,a[mid].c[1]); a[mid].sz=a[a[mid].c[0]].sz+a[a[mid].c[1]].sz+1; return mid; } int Built(int l,int r,int now){ int mid=(l+r)>>1; d=now;nth_element(st+l,st+mid,st+r+1); int x=newnode(mid); if(l<mid)a[x].c[0]=Built(l,mid-1,now^1),up(x,a[x].c[0]); if(r>mid)a[x].c[1]=Built(mid+1,r,now^1),up(x,a[x].c[1]); a[x].sz=a[a[x].c[0]].sz+a[a[x].c[1]].sz+1; return x; } void dfs(int x){ if(!x)return ; dfs(a[x].c[0]); st[++tot1]=a[x];St[++tot]=x; dfs(a[x].c[1]); } void check(int &x,int now){ if(alpha*a[x].sz<a[a[x].c[0]].sz||alpha*a[x].sz<a[a[x].c[1]].sz){ tot=tot1=0;dfs(x); x=Built(1,tot1,now); } } void insert(int &x,int now){ if(!x){x=n;a[x].sz=1;return ;} if(a[n].p[now]<a[x].p[now]){ insert(a[x].c[0],now^1); } else{ insert(a[x].c[1],now^1); } if(a[x].c[0])up(x,a[x].c[0]); if(a[x].c[1])up(x,a[x].c[1]); a[x].sz=a[a[x].c[0]].sz+a[a[x].c[1]].sz+1; check(x,now); } node que;int ans; int get_ans(node x,node y){ int ans1=0; inc(i,0,1)ans1+=abs(x.p[i]-y.p[i]); return ans1; } int getis(node x,node y){ int ans1=0; inc(i,0,1){ if(y.p[i]<x.minn[i])ans1+=x.minn[i]-y.p[i]; if(y.p[i]>x.maxx[i])ans1+=y.p[i]-x.maxx[i]; } return ans1; } void querty(int x){ if(!x)return ; ans=min(get_ans(que,a[x]),ans); int t1=(a[x].c[0]!=0)?getis(a[a[x].c[0]],que):inf; int t2=(a[x].c[1]!=0)?getis(a[a[x].c[1]],que):inf; if(t1<t2){ if(t1<ans)querty(a[x].c[0]); if(t2<ans)querty(a[x].c[1]); } else{ if(t2<ans)querty(a[x].c[1]); if(t1<ans)querty(a[x].c[0]); } } int main(){ n=read();m=read();a[0].sz=0; inc(i,1,n)a[i].p[0]=read(),a[i].p[1]=read(); rt=built(1,n,0); int op; while(m--){ op=read(); if(op==1){ n++;a[n].p[0]=read();a[n].p[1]=read();a[n].c[0]=a[n].c[1]=0; inc(j,0,1)a[n].minn[j]=a[n].maxx[j]=a[n].p[j]; insert(rt,0); } else{ que.p[0]=read();que.p[1]=read();ans=inf; querty(rt); printf("%d\n",ans); } } return 0; }
2716: [Violet 3]天使玩偶
Time Limit: 80 Sec Memory Limit: 128 MBSubmit: 2744 Solved: 1184
[Submit][Status][Discuss]