[IOI2018] werewolf 狼人 - 解题报告
Posted daniel14311531
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[IOI2018] werewolf 狼人 - 解题报告相关的知识,希望对你有一定的参考价值。
题意:
有一张无向图,一个人他需要从s走到t。他有两种形态,第一种形态可以走点编号为 [ li,n],第二种形态可以走点编号为 [ 1,ri],可以点编号为 [ li,n]切换形态(恰好一次),在起点时为第一种形态。求他是否能从s走到t。多组询问。
题解:
首先我们可以维护与起点联通的点集合(形态一),同时也可以维护维护与终点联通的点集合(形态二),显然可以用Kruskal重构树维护。用主席树维护两棵重构树其中子树是否有并集(二位数点)。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=400010; 4 int n,m,q,fa[N],w[N]; 5 vector <int> e[N]; 6 int tot=0,rt[N],lf[N*25],rf[N*25],sum[N*25]; 7 8 inline int read() { 9 register int tmp=0;register char c=getchar(); while(c<‘0‘||c>‘9‘) c=getchar(); 10 while(c>=‘0‘&&c<=‘9‘) tmp=(tmp<<1)+(tmp<<3)+(c^48),c=getchar();return tmp; 11 } 12 //inline int Max(int x,int y) { return x>y? x:y; } 13 //inline int Min(int x,int y) { return x<y? x:y; } 14 int Find(int x) { return x==fa[x]? x:fa[x]=Find(fa[x]); } 15 struct Kruskal { 16 int type; 17 int cnt,hed[N],to[N],nxt[N]; 18 int tot,w[N],idx,dfn[N],bg[N],ed[N]; 19 int st[N][20]; 20 inline void add(int x,int y) { to[++cnt]=y,nxt[cnt]=hed[x],hed[x]=cnt; } 21 void dfs(int u) { 22 dfn[bg[u]=++idx]=u; for(int i=1;i<20;i++) st[u][i]=st[st[u][i-1]][i-1]; 23 for(int i=hed[u];i;i=nxt[i]) dfs(to[i]); 24 ed[u]=idx; 25 } 26 void build() { 27 tot=n; for(int i=1;i<=n;++i) fa[i]=i; 28 if(type) { 29 for(int i=n;i;--i) 30 for(int j=0;j<e[i].size();++j) 31 if(i<e[i][j]) { 32 int v=Find(e[i][j]); if(i==v) continue; 33 add(i,v);fa[v]=st[v][0]=i; 34 } 35 dfs(1); 36 } 37 else { 38 for(int i=1;i<=n;++i) 39 for(int j=0;j<e[i].size();++j) 40 if(i>e[i][j]) { 41 int v=Find(e[i][j]); if(i==v) continue; 42 add(i,v);fa[v]=st[v][0]=i; 43 } 44 dfs(n); 45 } 46 } 47 inline int find(int u,int x) { 48 for(int i=19;i>=0;i--) 49 if(st[u][i]&&((type&&x<=st[u][i])||(!type&&x>=st[u][i]))) 50 u=st[u][i]; 51 return u; 52 } 53 };Kruskal mn,mx;// mn:people mx:wolf 54 55 void update(int &u,int v,int l,int r,int x) { 56 sum[u=++tot]=sum[v]+1,lf[u]=lf[v],rf[u]=rf[v]; if(l>=r) return ; 57 int mid=(l+r)>>1; x<=mid? update(lf[u],lf[v],l,mid,x):update(rf[u],rf[v],mid+1,r,x); 58 } 59 int ask(int u,int v,int l,int r,int L,int R) { 60 if(l==L&&r==R) return sum[v]-sum[u]; 61 int mid=(l+r)>>1; 62 if(R<=mid) return ask(lf[u],lf[v],l,mid,L,R); 63 if(L>mid) return ask(rf[u],rf[v],mid+1,r,L,R); 64 return ask(lf[u],lf[v],l,mid,L,mid)+ask(rf[u],rf[v],mid+1,r,mid+1,R); 65 } 66 int main() { 67 n=read(),m=read(),q=read(); 68 for(int i=1,x,y;i<=m;++i) x=read()+1,y=read()+1,e[x].push_back(y),e[y].push_back(x); 69 mn.type=1,mn.build(),mx.build(); 70 for(int i=1;i<=n;++i) w[mn.bg[i]]=mx.bg[i]; 71 for(int i=1;i<=n;++i) update(rt[i],rt[i-1],1,n,w[i]); 72 for(;q;--q) { 73 int s=read()+1,t=read()+1,l=read()+1,r=read()+1; 74 s=mn.find(s,l),t=mx.find(t,r); 75 if(ask(rt[mn.bg[s]-1],rt[mn.ed[s]],1,n,mx.bg[t],mx.ed[t])) printf("1 "); 76 else printf("0 "); 77 } 78 return 0; 79 }
以上是关于[IOI2018] werewolf 狼人 - 解题报告的主要内容,如果未能解决你的问题,请参考以下文章