“20121-2022-1學期20212322劉海浩《網路空間安全專業導論》第二週學習總結”
阿新 • • 發佈:2021-10-08
題解
搞一個尤拉序出來,先考慮刪點,設某個點 \(x\) 在尤拉序上第一次出現的位置為 \(fst_x\),最後一次出現的位置為 \(lst_x\),那麼刪掉的點就是 \(\{a|\min\limits_{i=l}^{i\leq r}(fst_i)=fst_a\lor\max\limits_{i=l}^{i\leq r}(lst_i)=lst_a\}\),也就是 \(fst_a\) 最小或 \(lst_a\) 最大。
對每個點找一下 \(fst,lst\),然後建出兩個 ST 表分別維護區間 \(\min\) 和 \(\max\) 的位置就可以 \(O(1)\) 找到被刪掉的兩個點。
刪掉一個點之後,\([l,r]\)
注意我們建了三個 ST 表,分別維護的是節點序列的 \(fst\) 值、\(lst\) 值和尤拉序上的 \(dep\) 值,所以時間複雜度是 \(O(n\log n+q)\)。
程式碼
#include<bits/stdc++.h> using namespace std; using ll=long long; inline int qread(){ int ret=0;char buf=getchar();bool neg=false; while(!isdigit(buf)){if(buf=='-'){neg=true;}buf=getchar();} while(isdigit(buf)){ret=ret*10+buf-'0';buf=getchar();} return neg?-ret:ret; } vector<int> Es[100005]; void addE(int fr,int to){ Es[fr].emplace_back(to); } int dep[100005]; int eula[200005]; int idx=0; int lb[100005],rb[100005]; void dfs(int nw,int fa){ dep[nw]=dep[fa]+1; eula[++idx]=dep[nw]; lb[nw]=idx; rb[nw]=idx; for(auto it:Es[nw]){ if(it==fa) continue; dfs(it,nw); eula[++idx]=dep[nw]; rb[nw]=idx; } } int logn[200005]; void pre(int n){ logn[1]=0;logn[2]=1; for(int i=3;i<n;i++) logn[i]=logn[i>>1]+1; } struct EST{ // if min == frm[pos], return frm[pos]; int st[18][200005]; void init(int* frm,int len){ memset(st,0x33,sizeof(st)); for(int i=1;i<=len;i++) st[0][i]=frm[i]; for(int j=1;j<=17;j++) for(int i=1;i<=len;i++) st[j][i]=min(st[j-1][i],st[j-1][max(i-(1<<(j-1)),1)]); } int RMinQ(int l,int r){ int j=logn[r-l+1]; return min(st[j][r],st[j][max(l-1+(1<<j),1)]); } }est; struct PST{ // if min/max == ffr[pos], return pos; int st[17][100005]; int* ffr=NULL; bool mint=true; // true --> get min_pos, false --> get max_pos void init(int* frm,int len,bool minv){ mint=minv; ffr=frm; memset(st,0x33,sizeof(st)); for(int i=0;i<=len;i++) st[0][i]=i; if(mint) for(int j=1;j<=16;j++) for(int i=1;i<=len;i++) if(frm[st[j-1][i]]<frm[st[j-1][max(i-(1<<(j-1)),1)]]) st[j][i]=st[j-1][i]; else st[j][i]=st[j-1][max(i-(1<<(j-1)),1)]; else for(int j=1;j<=16;j++) for(int i=1;i<=len;i++) if(frm[st[j-1][i]]>frm[st[j-1][max(i-(1<<(j-1)),1)]]) st[j][i]=st[j-1][i]; else st[j][i]=st[j-1][max(i-(1<<(j-1)),1)]; } int RMQ(int l,int r){ int j=logn[r-l+1]; if(mint) if(ffr[st[j][r]]<ffr[st[j][max(l-1+(1<<j),1)]]) return st[j][r]; else return st[j][max(l-1+(1<<j),1)]; else if(ffr[st[j][r]]>ffr[st[j][max(l-1+(1<<j),1)]]) return st[j][r]; else return st[j][max(l-1+(1<<j),1)]; } }ltt,rtt; int main(){ int n=qread(),q=qread(); for(int i=1;i<=n-1;i++){ int lt=qread(); addE(i+1,lt); addE(lt,i+1); } dep[0]=-1; dfs(1,0); pre(idx); est.init(eula,idx); ltt.init(lb,n,true); rtt.init(rb,n,false); for(int i=1;i<=q;i++){ int l=qread(),r=qread(); int lp=ltt.RMQ(l,r),lpdep; {int dfsmin=9982443,dfsmax=-1; if(lp!=l){ dfsmin=min(dfsmin,lb[ltt.RMQ(l,lp-1)]); dfsmax=max(dfsmax,rb[rtt.RMQ(l,lp-1)]); } if(lp!=r){ dfsmin=min(dfsmin,lb[ltt.RMQ(lp+1,r)]); dfsmax=max(dfsmax,rb[rtt.RMQ(lp+1,r)]); } lpdep=est.RMinQ(dfsmin,dfsmax);} int rp=rtt.RMQ(l,r),rpdep; {int dfsmin=9982443,dfsmax=-1; if(rp!=l){ dfsmin=min(dfsmin,lb[ltt.RMQ(l,rp-1)]); dfsmax=max(dfsmax,rb[rtt.RMQ(l,rp-1)]); } if(rp!=r){ dfsmin=min(dfsmin,lb[ltt.RMQ(rp+1,r)]); dfsmax=max(dfsmax,rb[rtt.RMQ(rp+1,r)]); }rpdep=est.RMinQ(dfsmin,dfsmax);} int ans=lpdep>rpdep?lp:rp; printf("%d %d\n",ans,max(lpdep,rpdep)); } }