BZOJphp
線段樹合併ios
線段樹合併是一個頗有趣的姿式spa
前置技能:動態開點線段樹code
具體實現:每次合併兩棵線段樹的時候,假設叫作\(t1,t2\),其中要把\(t2\)合併進\(t1\)中遞歸
假設當前位置\(t1\)沒有節點,則直接把\(t2\)的這個位置給\(t1\)(直接接上去就好啦)get
若是\(t2\)這個位置沒有節點,那麼直接\(return\)string
不然,兩個位置都有節點,把兩個節點的信息合併,而後遞歸合併左右子樹it
簡單的代碼以下:io
void MergeNode(int &r1,int r2) { if(!r1){r1=r2;return;} if(!r2)return; t[r1].v+=t[r2].v; MergeNode(t[r1].ls,t[r2].ls); MergeNode(t[r1].rs,t[r2].rs); }
回到這道題目class
對於每個聯通快維護一個值域線段樹
每次在線段樹上二分一下第\(K\)大就行了
每次修橋至關於合併兩棵線段樹
用並查集維護一下聯通快就能夠啦,多簡單
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<set> #include<map> #include<vector> #include<queue> using namespace std; #define ll long long #define RG register #define MAX 120000 inline int read() { RG int x=0,t=1;RG char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=-1,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return x*t; } int n,m,Q; struct Node { int ls,rs; int v; }t[MAX<<4]; int tot; int a[MAX]; void Modify(int &x,int l,int r,int p) { if(!x)x=++tot;t[x].v++; if(l==r)return; int mid=(l+r)>>1; if(p<=mid)Modify(t[x].ls,l,mid,p); else Modify(t[x].rs,mid+1,r,p); } void MergeNode(int &r1,int r2) { if(!r1){r1=r2;return;} if(!r2)return; t[r1].v+=t[r2].v; MergeNode(t[r1].ls,t[r2].ls); MergeNode(t[r1].rs,t[r2].rs); } int Query(int x,int l,int r,int K) { if(l==r)return l; int mid=(l+r)>>1; if(K<=t[t[x].ls].v)return Query(t[x].ls,l,mid,K); else return Query(t[x].rs,mid+1,r,K-t[t[x].ls].v); } int f[MAX],rt[MAX]; int getf(int x){return x==f[x]?x:f[x]=getf(f[x]);} int main() { n=read();m=read(); for(int i=1;i<=n;++i) { int x=read();a[x]=i; Modify(rt[f[i]=i],1,n,x); } while(m--) { int a=read(),b=read(); a=getf(a);b=getf(b); if(a==b)continue; f[b]=a; MergeNode(rt[a],rt[b]); } Q=read(); char opt[5]; while(Q--) { scanf("%s",opt); if(opt[0]=='Q') { int x=read(),k=read(); x=getf(x); if(t[rt[x]].v<k)puts("-1"); else printf("%d\n",a[Query(rt[x],1,n,k)]); } else { int u=read(),v=read(); u=getf(u),v=getf(v); if(u==v)continue; f[v]=u; MergeNode(rt[u],rt[v]); } } return 0; }