P4899 [IOI2018] werewolf 狼人
P4899 [IOI2018] werewolf 狼人
又是欢乐的 kruskal 重构树捏。
首先我们来仔细研读一下题目:
当你是人形时,你必须避开城市
也就是说,从起点开始,你只能走
以“起点树”为例:
一颗重构树的实点权为该点的编号,虚点权为该树下点权的最小值 ,这样我们就能保证在此树下,只要满足
由于这个式子
那么对于终点树:
我们用虚点维护该树下所有点的最大值
,我们需要满足的条件是
我们显然希望
我们求完了这两颗重构树了之后在他们上面跑倍增和
然而判断是否有交当然又是我们 喜闻乐见 的主席树环节了:
我是对于起点树来建的主席树:
对于 起点树 上的一个
那么我们查询的时候只需要知道终点在终点树上对应的节点
在
Code:
#include<bits/stdc++.h> const int N=4e5+5; const int lg=20; using namespace std; int n,m,Q,e_cnt,ans; struct Grapgh{ int head[N]; struct Edge{ int to,nxt; }e[N<<2]; void add(int x,int y) { e[++e_cnt]=Edge{y,head[x]}; head[x]=e_cnt; } void init() { for(int i=0;i<N;i++)head[i]=0; e_cnt=0; } int tot; int f[N][lg+5]; int st[N],ed[N],pos[N],siz[N],w[N]; void dfs(int x,int fa) { pos[++tot]=x;st[x]=tot; f[x][0]=fa; for(int j=1;j<=lg;j++)f[x][j]=f[f[x][j-1]][j-1]; for(int i=head[x],y;i;i=e[i].nxt) { y=e[i].to; if(y==f[x][0])continue; dfs(y,x); siz[x]+=siz[y]; } if(!siz[x])siz[x]=1; ed[x]=tot; } int get_lower(int x,int k) { for(int i=lg;i>=0;i--)if(w[f[x][i]]<=k&&f[x][i])x=f[x][i]; return x; } int get_upper(int x,int k) { for(int i=lg;i>=0;i--)if(w[f[x][i]]>=k&&f[x][i])x=f[x][i]; return x; } }G1,G2; struct edge{ int u,v; }q[N<<1]; bool cmp1(edge e1,edge e2){ return (e1.u<e1.v ? e1.u : e1.v)>(e2.u<e2.v ? e2.u : e2.v); } bool cmp2(edge e1,edge e2){ return (e1.u>e1.v ? e1.u : e1.v)<(e2.u>e2.v ? e2.u : e2.v); } struct Kruskal{ int fa[N]; int tot; int find(int x){return fa[x] = fa[x]==x ? fa[x] : find(fa[x]);} void build(int tag,Grapgh &G) { tot=n; for(int i=0;i<N;i++)fa[i]=i; for(int i=0;i<n;i++)G.w[i]=i; for(int i=1;i<=m;i++) { int x=find(q[i].u),y=find(q[i].v); if(x!=y) { G.w[++tot]= (tag ? (G.w[x] > G.w[y] ? G.w[x] : G.w[y]) : (G.w[x] < G.w[y] ? G.w[x] : G.w[y])); G.add(tot,x);G.add(tot,y); fa[tot]=fa[x]=fa[y]=tot; } } } }K; //Segment_Tree struct Segment_Tree{ int rt[N],cnt; struct Tree{ int ls,rs,cnt; }t[N*40]; void insert(int &x,int y,int l,int r,int pos) { t[x=++cnt]=t[y]; t[x].cnt++; if(l==r)return ; int mid=l+r>>1; if(pos<=mid)insert(t[x].ls,t[y].ls,l,mid,pos); if(mid<pos) insert(t[x].rs,t[y].rs,mid+1,r,pos); } int query(int x,int y,int l,int r,int L,int R) { if(R<L||!y)return 0; if(L<=l&&r<=R) { return -t[x].cnt+t[y].cnt; } int mid=l+r>>1; int res=0; if(L<=mid)res+=query(t[x].ls,t[y].ls,l,mid,L,R); if(mid<R) res+=query(t[x].rs,t[y].rs,mid+1,r,L,R); return res; } }T; int idd[N]; void work() { cin>>n>>m>>Q; for(int i=1;i<=m;i++) { scanf("%d%d",&q[i].u,&q[i].v); } sort(q+1,q+1+m,cmp1); K.build(0,G1); G1.dfs(K.tot,K.tot); sort(q+1,q+1+m,cmp2); K.build(1,G2); G2.dfs(K.tot,K.tot); for(int i=1;i<=G1.tot;i++) { if(G1.pos[i]<=n) { int x=G1.pos[i]; T.insert(T.rt[i],T.rt[i-1],0,N,G2.st[x]); } else { T.rt[i]=T.rt[i-1]; } } for(int i=1,s,t,l,r;i<=Q;i++) { scanf("%d%d%d%d",&s,&t,&l,&r); s=G1.get_upper(s,l); t=G2.get_lower(t,r); ans=T.query(T.rt[G1.st[s]-1],T.rt[G1.ed[s]],0,N,G2.st[t],G2.ed[t]); ans = ans>0 ? 1 : 0; printf("%d\n",ans); } } int main() { //freopen("werewolf.in","r",stdin);freopen("werewolf.out","w",stdout); work(); return 0; }