1. 程式人生 > >BZOJ3123:[SDOI2013]森林——題解

BZOJ3123:[SDOI2013]森林——題解

debug 然而 sdoi2013 getch IT .org url () +++

http://www.lydsy.com/JudgeOnline/problem.php?id=3123

https://www.luogu.org/problemnew/show/P3302

技術分享圖片

樹上主席樹操作方法看:http://www.cnblogs.com/luyouqi233/p/8159528.html

(BZOJ2588:Count on a tree)

這題要動態樹,顯然不可能LCT套主席樹啊。

那我們完全可以啟發式合並一下主席樹。

剩下的操作就很簡單了。

(然而我debug兩個小時才發現我n定義了兩個emmmm)

#include<cstdio>
#include
<cmath> #include<cstring> #include<cctype> #include<iostream> #include<algorithm> using namespace std; const int N=8e4+10; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch==-;ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1
)+(ch^48),ch=getchar(); return w?-X:X; } struct tree{ int l,r,sum; }tr[N*500]; struct node{ int to,nxt; }edge[N*2]; int a[N],b[N],rt[N],pool,n,m; int dep[N],anc[N][20],son[N]; int cnt,head[N],fa[N],vis[N],tot; inline void add(int u,int v){ edge[++cnt].to=v;edge[cnt].nxt=head[u];head[u]=cnt; } inline
void insert(int y,int &x,int l,int r,int p){ tr[x=++pool]=tr[y];tr[x].sum++; if(l==r)return; int mid=(l+r)>>1; if(p<=mid)insert(tr[y].l,tr[x].l,l,mid,p); else insert(tr[y].r,tr[x].r,mid+1,r,p); } inline int query(int nl,int nr,int nm,int nfm,int l,int r,int k){ if(l==r)return l; int delta=tr[tr[nl].l].sum+tr[tr[nr].l].sum-tr[tr[nm].l].sum-tr[tr[nfm].l].sum; int mid=(l+r)>>1; if(delta>=k)return query(tr[nl].l,tr[nr].l,tr[nm].l,tr[nfm].l,l,mid,k); else return query(tr[nl].r,tr[nr].r,tr[nm].r,tr[nfm].r,mid+1,r,k-delta); } inline void LSH(){ sort(b+1,b+m+1); m=unique(b+1,b+m+1)-b-1; for(int i=1;i<=n;i++){ a[i]=lower_bound(b+1,b+m+1,a[i])-b; } return; } inline int LCA(int i,int j){ if(dep[i]<dep[j])swap(i,j); for(int k=16;k>=0;k--){ if(dep[anc[i][k]]>=dep[j])i=anc[i][k]; } if(i==j)return i; for(int k=16;k>=0;k--){ if(anc[i][k]!=anc[j][k])i=anc[i][k],j=anc[j][k]; } return anc[i][0]; } int find(int x){ if(fa[x]==x)return x; return fa[x]=find(fa[x]); } void dfs(int u,int f,int root){ anc[u][0]=f; for(int k=1;k<=16;k++) anc[u][k]=anc[anc[u][k-1]][k-1]; son[root]++;dep[u]=dep[f]+1;fa[u]=root;vis[u]=1; insert(rt[f],rt[u],1,m,a[u]); for(int i=head[u];i;i=edge[i].nxt){ int v=edge[i].to; if(v!=f)dfs(v,u,root); } return; } int main(){ read(); n=read();int e=read(),T=read(),last=0; for(int i=1;i<=n;i++) a[i]=b[++m]=read(),fa[i]=i; LSH(); for(int i=1;i<=e;i++){ int x=read(),y=read(); add(x,y);add(y,x); } for(int i=1;i<=n;i++) if(!vis[i]){ dfs(i,0,++tot);fa[tot]=tot; } for(int i=1;i<=T;i++){ char ch=getchar(); while(ch!=Q&&ch!=L)ch=getchar(); if(ch==Q){ int x=read()^last,y=read()^last,k=read()^last; int t=LCA(x,y),ft=anc[t][0]; printf("%d\n",last=b[query(rt[x],rt[y],rt[t],rt[ft],1,m,k)]); }else{ int x=read()^last,y=read()^last; add(x,y);add(y,x); int u=find(x),v=find(y); if(son[u]<son[v]){ swap(u,v); swap(x,y); } dfs(y,x,u); } } return 0; }

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+歡迎訪問我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

BZOJ3123:[SDOI2013]森林——題解