Codeforces 1062 E. Company
在自闭的边缘疯狂试探。。。。
题目直通车:http://codeforces.com/contest/1062/problem/E
lca+线段树
首先要明白题意,即删除[l,r]中的任意一个元素,使得其他点的最近公共祖先的深度最大
在树的点区间上建立线段树,维护区间的 所有点的最近公共祖先,不包含最左点的公共祖先,不包含最右点的公共祖先,不包含任意一点的其他点的深度最大的公共祖先和相应的不包含的点的id(序号),在线段树上依次维护,不包含任意一点的其他点的深度最大的公共祖先可以由该区间的左右区间分别得到,具体细节参见代码
#include<iostream> #include<cstdio> #include<cmath> #include<queue> #include<vector> #include<string.h> #include<cstring> #include<algorithm> #include<set> #include<stack> #include<map> #include<fstream> #include<cstdlib> #include<ctime> #include<list> #include<climits> #include<bitset> #include<random> using namespace std; #define fopen freopen("input.in", "r", stdin);freopen("output.in", "w", stdout); #define left asfdasdasdfasdfsdfasfsdfasfdas1 #define right asfdasdasdfasdfsdfasfsdfasfdas2 #define y1 asfdasdasdfasdfsdfasfsdfasfdas3 typedef long long ll; typedef unsigned ui; typedef long double ld; const int dell[8][2]={{1,2},{1,-2},{2,1},{2,-1},{-1,2},{-1,-2},{-2,1},{-2,-1}}; ll mod=1e9+7; const ll inf=(1LL<<31)-1; const int maxn=1e5+7; const int maxm=1e6+7; const double eps=1e-8; const double pi=acos(-1.0); const int csize=22; int n,k,m,ar[maxn]; struct node{ int b,nex; }no[maxn]; int head[maxn],sz; int ft[maxn<<1],st[maxn<<1],dfs_clock,pos[maxn],ta[maxn<<1][20],dep[maxn]; void init(){ memset(head,-1,sizeof(head)); sz=0; dfs_clock=0; } void add(int a,int b){ no[sz].b=b; no[sz].nex=head[a]; head[a]=sz++; } void dfs(int u,int fa){ dep[u]=dep[fa]+1; st[dfs_clock]=u; pos[u]=dfs_clock++; for(int i=head[u];i!=-1;i=no[i].nex){ int v=no[i].b; if(v==fa)continue; dfs(v,u); st[dfs_clock++]=u; } } void init_rmq(){ memset(ta,0,sizeof(ta)); for(int i=0;i<dfs_clock;i++)ta[i][0]=st[i]; for(int j=1;j<20;j++){ for(int i=0;i<dfs_clock;i++){ if(i+(1<<j)-1>=dfs_clock)break; if(dep[ta[i][j-1]]<dep[ta[i+(1<<j-1)][j-1]])ta[i][j]=ta[i][j-1]; else ta[i][j]=ta[i+(1<<j-1)][j-1]; } } } int samefather(int a,int b){ a=pos[a]; b=pos[b]; if(a>b)swap(a,b); int ins=0; while((1<<1+ins)<=b-a+1)ins++; if(dep[ta[a][ins]]<dep[ta[b-(1<<ins)+1][ins]])return ta[a][ins]; else return ta[b-(1<<ins)+1][ins]; } int mn1[maxn<<3],mn2[maxn<<3],pp[maxn<<3]; int mn[maxn<<3],mn3[maxn<<3]; int x,y; void build(int l,int r,int o){ if(l==r-1){ mn[o]=samefather(l,r); if(dep[l]<dep[r]){ mn3[o]=r; pp[o]=l; } else{ mn3[o]=l; pp[o]=r; } mn1[o]=r; mn2[o]=l; return ; } int mid=l+r>>1; build(l,mid,o<<1); build(mid,r,o<<1|1); mn1[o]=samefather(mn1[o<<1],mn[o<<1|1]); mn2[o]=samefather(mn[o<<1],mn2[o<<1|1]); mn[o]=samefather(mn[o<<1],mn[o<<1|1]); mn3[o]=0; if(dep[mn3[o]]<dep[mn1[o]]){ mn3[o]=mn1[o]; pp[o]=l; } if(dep[mn3[o]]<dep[mn2[o]]){ mn3[o]=mn2[o]; pp[o]=r; } int val=samefather(mn2[o<<1],mn1[o<<1|1]); if(dep[mn3[o]]<dep[val]){ mn3[o]=val; pp[o]=mid; } val=samefather(mn3[o<<1],mn[o<<1|1]); if(dep[mn3[o]]<dep[val]){ mn3[o]=val; pp[o]=pp[o<<1]; } val=samefather(mn[o<<1],mn3[o<<1|1]); if(dep[mn3[o]]<dep[val]){ mn3[o]=val; pp[o]=pp[o<<1|1]; } //cout<<l<<" "<<r<<" "<<mn[o]<<" "<<mn3[o]<<endl; } void que(int l,int r,int o,int &mm,int &m1,int& m2,int& m3,int& p){ //cout<<l<<" "<<r<<endl; if(l>=x && r<=y){ mm=mn[o];m1=mn1[o];m2=mn2[o];m3=mn3[o];p=pp[o]; return ; } int mid=l+r>>1; if(y<=mid){ que(l,mid,o<<1,mm,m1,m2,m3,p); } else if(x>=mid){ que(mid,r,o<<1|1,mm,m1,m2,m3,p); } else{ int mm1,mm2,m11,m12,m21,m22,m31,m32,p1,p2; que(l,mid,o<<1,mm1,m11,m21,m31,p1); que(mid,r,o<<1|1,mm2,m12,m22,m32,p2); m1=samefather(m11,mm2); m2=samefather(mm1,m22); mm=samefather(mm1,mm2); m3=0; if(dep[m3]<dep[m1]){ m3=m1; p=x; } if(dep[m3]<dep[m2]){ m3=m2; p=y; } int val=samefather(m21,m12); if(dep[m3]<dep[val]){ m3=val; p=mid; } val=samefather(m31,mm2); if(dep[m3]<dep[val]){ m3=val; p=p1; } val=samefather(mm1,m32); if(dep[m3]<dep[val]){ m3=val; p=p2; } } } int main() { //fopen //freopen("input.in","r",stdin); scanf("%d%d",&n,&m); init(); for(int i=2;i<=n;i++){ int x;scanf("%d",&x); add(x,i); } dep[0]=-1; dfs(1,0); init_rmq(); build(1,n,1); while(m--){ scanf("%d%d",&x,&y); //cout<<"x,y = "<<x<<" "<<y<<endl; int mm,m1,m2,m3,p; que(1,n,1,mm,m1,m2,m3,p); //cout<<"m3 = "<<m3<<endl; printf("%d %d\n",p,dep[m3]); } return 0; }