正题
P4899
题目大意
给你一个图,对于每次询问Si,Ei,Li,RiS_i,E_i,L_i,R_iSi,Ei,Li,Ri,回答从SiS_iSi走到EiE_iEi,是否存在路径满足前面一段只经过Li∼n−1L_i\sim n-1Li∼n−1,后面一段只经过0∼Ri0\sim R_i0∼Ri
解题思路
先正序倒序各建立一个Kruskal重构树
然后以dfnAdfn_AdfnA建立主席树,每个点的主席树中在dfnBdfn_BdfnB的位置+1
那么查询时,直接查询前面一段的主席树中,后面一段的区间是否有值即可
code
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define N 400021
using namespace std;
int n,m,q,x,y,l,r,w,s,t,xx,yy,tot,v[N],h[N],f[N],rt[N];
struct rec
{int to,nx;
}e[N<<1];
struct node
{int nm,mx[N],mn[N],to1[N],to2[N],dfn[N],low[N],fa[N][20];void dfs(int x){for(int i=1;i<=16;++i)fa[x][i]=fa[fa[x][i-1]][i-1];if(!to1[x]){dfn[x]=low[x]=++nm;mx[x]=mn[x]=x;return;}dfn[x]=nm+1;fa[to1[x]][0]=x;fa[to2[x]][0]=x;dfs(to1[x]);dfs(to2[x]);mx[x]=max(mx[to1[x]],mx[to2[x]]);mn[x]=min(mn[to1[x]],mn[to2[x]]);low[x]=nm;return;}int getA(int x,int mnn){for(int i=16;i>=0;--i)if(mn[fa[x][i]]>=mnn)x=fa[x][i];return x;}int getB(int x,int mxx){for(int i=16;i>=0;--i)if(mx[fa[x][i]]<=mxx)x=fa[x][i];return x;}
}A,B;
struct Tree
{#define ls son[x][0]#define rs son[x][1]int nm,s[N<<4],son[N<<4][2];int build(int l,int r){int x=++nm;if(l==r)return x;int mid=l+r>>1;ls=build(l,mid);rs=build(mid+1,r);return x;}int add(int lst,int l,int r,int y){int x=++nm;if(l==r){s[x]=1;return x;}int mid=l+r>>1;if(y<=mid){rs=son[lst][1];ls=add(son[lst][0],l,mid,y);}else{ls=son[lst][0];rs=add(son[lst][1],mid+1,r,y);}s[x]=s[ls]+s[rs];return x;}int ask(int x,int L,int R,int l,int r){if(L==l&&R==r)return s[x];int mid=L+R>>1;if(r<=mid)return ask(ls,L,mid,l,r);else if(l>mid)return ask(rs,mid+1,R,l,r);else return ask(ls,L,mid,l,mid)+ask(rs,mid+1,R,mid+1,r);}
}T;
int find(int x)
{return f[x]==x?x:f[x]=find(f[x]);
}
void add(int x,int y)
{e[++tot].to=y;e[tot].nx=h[x];h[x]=tot;return;
}
int main()
{scanf("%d%d%d",&n,&m,&q);for(int i=1;i<=m;++i){scanf("%d%d",&x,&y);x++;y++;add(x,y);add(y,x);}w=n;for(x=n;x>=1;--x){f[x]=x;for(int i=h[x];i;i=e[i].nx){int y=e[i].to;if(y<=x)continue;xx=find(x);yy=find(y);if(xx==yy)continue;A.to1[++w]=xx;A.to2[w]=yy;f[w]=w;f[xx]=w;f[yy]=w;}}w=n;for(x=1;x<=n;++x){f[x]=x;for(int i=h[x];i;i=e[i].nx){int y=e[i].to;if(y>=x)continue;xx=find(x);yy=find(y);if(xx==yy)continue;B.to1[++w]=xx;B.to2[w]=yy;f[w]=w;f[xx]=w;f[yy]=w;}}A.fa[2*n-1][0]=2*n-1;A.dfs(2*n-1);B.fa[2*n-1][0]=2*n-1;B.dfs(2*n-1);rt[0]=T.build(1,n);for(int i=1;i<=n;++i)v[A.dfn[i]]=B.dfn[i];for(int i=1;i<=n;++i)rt[i]=T.add(rt[i-1],1,n,v[i]);while(q--){scanf("%d%d%d%d",&s,&t,&l,&r);s++;t++;l++;r++;s=A.getA(s,l);//找到最高点t=B.getB(t,r);w=T.ask(rt[A.low[s]],1,n,B.dfn[t],B.low[t]);//前面一部分的点w-=T.ask(rt[A.dfn[s]-1],1,n,B.dfn[t],B.low[t]);if(w)puts("1");else puts("0");}return 0;
}