[SDOI2013]森林(树上主席树+启发式合并+lca)
鏈接:https://ac.nowcoder.com/acm/problem/20577
 來源:牛客網
題目描述
 小Z有一片森林,含有N個節點,每個節點上都有一個非負整數作為權值。初始的時候,森林中有M條邊。
 小Z希望執行T個操作,操作有兩類:
Q x y k查詢點x到點y路徑上所有的權值中,第k小的權值是多少。此操作保證點x和點y連通,同時這兩個節點的路徑上至少有k個點。
 L x y在點x和點y之間連接一條邊。保證完成此操作后,仍然是一片森林。
 為了體現程序的在線性,我們把輸入數據進行了加密。設lastans為程序上一次輸出的結果,初始的時候lastans為0。
對于一個輸入的操作Q x y k,其真實操作為Q x^lastans y^lastans k^lastans。
 對于一個輸入的操作L x y,其真實操作為L x^lastans ylastans。其中運算符表示異或,等價于pascal中的xor運算符。
 請寫一個程序來幫助小Z完成這些操作。
 對于所有的數據,n,m,T<= 8?10^4.
輸入描述:
 第一行包含一個正整數testcase,表示當前測試數據的測試點編號。保證1<=testcase<=20。
 第二行包含三個整數N,M,T,分別表示節點數、初始邊數、操作數。
 第三行包含N個非負整數表示 N個節點上的權值。
 接下來 M行,每行包含兩個整數x和 y,表示初始的時候,點x和點y 之間有一條無向邊。
 接下來 T行,每行描述一個操作,格式為”Q x y k“或者”L x y “,其含義見題目描述部分。
 輸出描述:
 對于每一個第一類操作,輸出一個非負整數表示答案。
 示例1
 輸入
 復制
 1
 8 4 8
 1 1 2 2 3 3 4 4
 4 7
 1 8
 2 4
 2 1
 Q 8 7 3 Q 3 5 1
 Q 10 0 0
 L 5 4
 L 3 2 L 0 7
 Q 9 2 5 Q 6 1 6
 輸出
 復制
 2
 2
 1
 4
 2
 備注:
 
 很毒瘤的一道題目。
 第一個輸入的不是組數,而是樣例的測試編號。。
 對于求路徑上第k小,就是主席樹的板子。
 但是對于合并兩棵樹,就需要點技巧的。類似于并查集一樣的,就需要小的往大的上面合并。這樣的話,耗時是最小的。總之這道題目很煩,不知道哪兒寫錯了,在洛谷上面只拿到了70分。。
 代碼如下:
 洛谷70分
滿分代碼:
#include<cstdio> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> #include<cstdlib> #define ll long long using namespace std; inline int read(){int x=0;char ch=' ';int f=1;while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();if(ch=='-')f=-1,ch=getchar();while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f; } struct edge{int to,next; }e[320001]; int T,n,m,q,tot; int a[80001]; int fa[80001]; int son[80001]; int head[80001]; inline void addedge(int x,int y){e[++tot].to=y;e[tot].next=head[x];head[x]=tot; } struct Node{int size,ls,rs; }t[80001*600]; int cnt; int root[80001]; void build(int &now,int l,int r){now=++cnt;t[now].size=0;if(l==r)return;int mid=(l+r)>>1;build(t[now].ls,l,mid);build(t[now].rs,mid+1,r); } void insert(int &now,int pre,int l,int r,int x){now=++cnt;t[now]=t[pre];t[now].size++;if(l==r)return;int mid=(l+r)>>1;if(x<=mid)insert(t[now].ls,t[pre].ls,l,mid,x);else insert(t[now].rs,t[pre].rs,mid+1,r,x); } int b[80001]; int size; int query(int x,int y,int pre1,int pre2,int l,int r,int k){if(l==r)return b[l];int lsize=t[t[x].ls].size+t[t[y].ls].size-t[t[pre1].ls].size-t[t[pre2].ls].size;int mid=(l+r)>>1;if(k<=lsize)return query(t[x].ls,t[y].ls,t[pre1].ls,t[pre2].ls,l,mid,k);else return query(t[x].rs,t[y].rs,t[pre1].rs,t[pre2].rs,mid+1,r,k-lsize); } inline int Hash(int x){return lower_bound(b+1,b+size+1,x)-b; } int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]); } int st[80001][17]; int dep[80001]; int vis[80001]; void dfs(int x,int father,int rt){st[x][0]=father;for(int k=1;k<=16;k++){st[x][k]=st[st[x][k-1]][k-1];}son[rt]++;dep[x]=dep[father]+1;fa[x]=father;vis[x]=1;insert(root[x],root[father],1,size,Hash(a[x]));for(int i=head[x];i;i=e[i].next){int u=e[i].to;if(u==father)continue;dfs(u,x,rt);} } inline int getlca(int x,int y){if(x==y)return x;if(dep[x]>dep[y])swap(x,y);for(int k=16;k>=0;k--){if(dep[st[y][k]]>=dep[x]){y=st[y][k];}}if(x==y)return x;for(int k=16;k>=0;k--){if(st[x][k]!=st[y][k]){x=st[x][k];y=st[y][k];}}return st[x][0]; } int main(){T=read();T=1;while(T--){memset(head,0,sizeof(head));memset(dep,0,sizeof(dep));memset(vis,0,sizeof(vis));memset(st,0,sizeof(st));memset(son,0,sizeof(son));tot=0;cnt=0;n=read();m=read();q=read();for(int i=1;i<=n;i++){a[i]=read();b[i]=a[i];fa[i]=i;}sort(b+1,b+n+1);size=unique(b+1,b+n+1)-b-1;for(int i=1;i<=m;i++){int x=read(),y=read();addedge(x,y);addedge(y,x);}build(root[0],1,size);for(int i=1;i<=n;i++){if(!vis[i]){dfs(i,0,i);fa[i]=i;}}int lastans=0;for(int i=1;i<=q;i++){char ch[3];int x,y,k;scanf("%s",ch);x=read()^lastans;y=read()^lastans;if(ch[0]=='Q'){k=read()^lastans;int lca=getlca(x,y);lastans=query(root[x],root[y],root[lca],root[st[lca][0]],1,size,k);printf("%d\n",lastans);}else{addedge(x,y);addedge(y,x);int u=find(x);int v=find(y);if(son[u]<son[v]){swap(u,v);swap(x,y);}dfs(y,x,u);}}}return 0; }乞求路過的大佬看看哪兒不對,跪謝。
 十一假期開啟,codeforces之路起航
 努力加油a啊,(o)/~
總結
以上是生活随笔為你收集整理的[SDOI2013]森林(树上主席树+启发式合并+lca)的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: Master of GCD(差分数组||
 - 下一篇: George and Job(动态规划)