[IOI2018]狼人
阿新 • • 發佈:2018-11-29
[IOI2018]狼人
luogu
UOJ
對人形和狼形分別建克魯斯卡爾重構樹
每次詢問就是對於兩棵樹dfs序的一個二維數點,主席樹維護
#include<bits/stdc++.h> using namespace std; const int _=4e5+5; int re(){ int x=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); return x*w; } int n,m,q,S,rt[_],s[_<<4],ls[_<<4],rs[_<<4]; struct Edge{int u,v,w;}E[_]; bool cmp1(Edge a,Edge b){return a.w>b.w;} bool cmp2(Edge a,Edge b){return a.w<b.w;} struct Kruskal_tree{ int tot,cnt,ts; int fa[_],val[_],f[20][_],r[_],id[_],h[_],dfn[_]; bool tag; struct edge{int to,next;}e[_]; int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} void link(int u,int v){e[++cnt]=(edge){v,h[u]};h[u]=cnt;} void dfs(int u){ dfn[u]=++ts;id[ts]=u; for(int i=h[u];i;i=e[i].next) dfs(e[i].to); r[u]=ts; } void init(){ tot=n; for(int i=1;i<=n<<1;i++)fa[i]=i; for(int i=1;i<=n;i++)val[i]=i; for(int i=1;i<=m;i++){//克魯斯卡爾重構樹 int x=find(E[i].u),y=find(E[i].v); if(x==y)continue; val[++tot]=E[i].w; link(tot,x);link(tot,y); f[0][x]=f[0][y]=fa[x]=fa[y]=tot; } for(int i=1;i<=18;i++)//預處理倍增陣列 for(int j=1;j<=tot;j++) f[i][j]=f[i-1][f[i-1][j]]; dfs(tot);//預處理dfs序 } int work(int x,int k){//倍增 for(int i=18;i>=0;i--) if(f[i][x]&&((val[f[i][x]]>=k&&tag)||(!tag&&val[f[i][x]]<=k))) x=f[i][x]; return x; } }man,wolf; void upd(int&x,int l,int r,int k){ s[++S]=s[x]+1;ls[S]=ls[x];rs[S]=rs[x]; x=S;if(l==r)return;int mid=(l+r)>>1; if(k<=mid)upd(ls[x],l,mid,k); else upd(rs[x],mid+1,r,k); } int query(int x,int y,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr)return s[y]-s[x]; int mid=(l+r)>>1,res=0; if(ql<=mid)res=query(ls[x],ls[y],l,mid,ql,qr); if(qr>mid)res+=query(rs[x],rs[y],mid+1,r,ql,qr); return res; } int main(){ n=re(),m=re(),q=re(); for(int i=1;i<=m;i++){ E[i].u=re()+1,E[i].v=re()+1; E[i].w=min(E[i].u,E[i].v); } man.tag=1; sort(E+1,E+m+1,cmp1); man.init(); for(int i=1;i<=m;i++)E[i].w=max(E[i].u,E[i].v); sort(E+1,E+m+1,cmp2); wolf.init(); //預處理主席樹 for(int i=1;i<=man.tot;i++){ rt[i]=rt[i-1]; if(man.id[i]<=n)upd(rt[i],1,wolf.tot,wolf.dfn[man.id[i]]); } while(q--){ int s=re()+1,t=re()+1,L=re()+1,R=re()+1; int A=man.work(s,L),B=wolf.work(t,R); if(query(rt[man.dfn[A]-1],rt[man.r[A]],1,wolf.tot,wolf.dfn[B],wolf.r[B]))puts("1"); else puts("0"); } return 0; }