F. Graph and Queries(反向并查集&dfs序&线段树)

    科技2022-07-14  132

    F. Graph and Queries(反向并查集&dfs序&线段树)

    思路:反向并查集 + d f s +dfs +dfs + + +线段树

    对询问进行离线操作,从后往前,最开始建立一张删除所有询问边后的图,然后倒着重构图,如果是操作一就更新查询结点为其祖先结点: Q [ i ] . s e = f i n d ( Q [ i ] . s e ) Q[i].se=find(Q[i].se) Q[i].se=find(Q[i].se)

    如果是操作二就利用并查集建立新结点连边,具体就是新建立一个结点其儿子为这条边的两个结点,父亲也同时更新为该新结点。

    然后对图跑 d f s dfs dfs序,然后转换为线段树求区间最值问题。

    #include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=5e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7; #define mst(a,b) memset(a,b,sizeof a) #define lx x<<1 #define rx x<<1|1 #define reg register #define PII pair<int,int> #define fi first #define se second #define pb push_back #define il inline int n,m,q,cnt; int a[N],f[N],in[N],out[N],pos[N],del[N]; PII edge[N],Q[N]; int find(int x){return x==f[x]?x:f[x]=find(f[x]);} vector<int>g[N]; struct node{ int l,r,mx; }tr[N<<2]; void Merge(int x,int y){ x=find(x),y=find(y); if(x==y) return; n++;f[n]=n,f[x]=f[y]=n; g[n].pb(x),g[n].pb(y); } void dfs(int u){ in[u]=++cnt; for(int v:g[u]) if(!in[v]) dfs(v); out[u]=cnt; } void re(int x){ tr[x].mx=max(tr[lx].mx,tr[rx].mx); } void build(int x,int l,int r){ tr[x].l=l,tr[x].r=r,tr[x].mx=0; if(l==r){ return; } int mid=(l+r)>>1; build(lx,l,mid); build(rx,mid+1,r); } void upd(int x,int p,int val){ if(tr[x].l==tr[x].r){ tr[x].mx=val;return; } int mid=(tr[x].l+tr[x].r)>>1; if(p<=mid) upd(lx,p,val); else upd(rx,p,val); re(x); } int que(int x,int l,int r){ if(tr[x].l>=l&&tr[x].r<=r) return tr[x].mx; int ans=0,mid=(tr[x].l+tr[x].r)>>1; if(l<=mid) ans=max(ans,que(lx,l,r)); if(r>mid) ans=max(ans,que(rx,l,r)); return ans; } int main(){ scanf("%d%d%d",&n,&m,&q); for(int i=1;i<=n;i++){ scanf("%d",&a[i]),pos[a[i]]=i,f[i]=i; } for(int i=1;i<=m;i++) scanf("%d%d",&edge[i].fi,&edge[i].se); for(int i=1;i<=q;i++){ scanf("%d%d",&Q[i].fi,&Q[i].se); if(Q[i].fi==2) del[Q[i].se]=1; } for(int i=1;i<=m;i++) if(!del[i]) Merge(edge[i].fi,edge[i].se); for(int i=q;i;i--){ if(Q[i].fi==1) Q[i].se=find(Q[i].se); else Merge(edge[Q[i].se].fi,edge[Q[i].se].se); } for(int i=1;i<=n;i++) if(f[i]==i) dfs(i); build(1,1,n); for(int i=1;i<=n;i++) upd(1,in[i],a[i]); for(int i=1;i<=q;i++){ if(Q[i].fi==1){ int ans=que(1,in[Q[i].se],out[Q[i].se]); printf("%d\n",ans); if(ans) upd(1,in[pos[ans]],0); } } return 0; }

    Processed: 0.010, SQL: 8