BZOJ 2733([HNOI2012]永无乡-Treap启发式合并)
2017-03-22 15:28
381 查看
2733: [HNOI2012]永无乡
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 3219 Solved: 1706
[Submit][Status][Discuss]
Description
永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛。如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b,则称岛 a 和岛 b 是连 通的。现在有两种操作:B x y 表示在岛 x 与岛 y 之间修建一座新桥。Q x k 表示询问当前与岛 x连通的所有岛中第 k 重要的是哪座岛,即所有与岛 x 连通的岛中重要度排名第 k 小的岛是哪 座,请你输出那个岛的编号。
Input
输入文件第一行是用空格隔开的两个正整数 n 和 m,分别 表示岛的个数以及一开始存在的桥数。接下来的一行是用空格隔开的 n 个数,依次描述从岛 1 到岛 n 的重要度排名。随后的 m 行每行是用空格隔开的两个正整数 ai 和 bi,表示一开始就存 在一座连接岛 ai 和岛 bi 的桥。后面剩下的部分描述操作,该部分的第一行是一个正整数 q, 表示一共有 q 个操作,接下来的 q 行依次描述每个操作,操作的格式如上所述,以大写字母 Q 或B 开始,后面跟两个不超过 n 的正整数,字母与数字以及两个数字之间用空格隔开。 对于 20%的数据 n≤1000,q≤1000
对于 100%的数据 n≤100000,m≤n,q≤300000
Output
对于每个 Q x k 操作都要依次输出一行,其中包含一个整数,表 示所询问岛屿的编号。如果该岛屿不存在,则输出-1。
Sample Input
5 1
4 3 2 5 1
1 2
7
Q 3 2
Q 2 1
B 2 3
B 1 5
Q 2 1
Q 2 4
Q 2 3
Sample Output
-1
2
5
1
2
用并查集维护连通性,再用Treap维护第k大
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 3219 Solved: 1706
[Submit][Status][Discuss]
Description
永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛。如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b,则称岛 a 和岛 b 是连 通的。现在有两种操作:B x y 表示在岛 x 与岛 y 之间修建一座新桥。Q x k 表示询问当前与岛 x连通的所有岛中第 k 重要的是哪座岛,即所有与岛 x 连通的岛中重要度排名第 k 小的岛是哪 座,请你输出那个岛的编号。
Input
输入文件第一行是用空格隔开的两个正整数 n 和 m,分别 表示岛的个数以及一开始存在的桥数。接下来的一行是用空格隔开的 n 个数,依次描述从岛 1 到岛 n 的重要度排名。随后的 m 行每行是用空格隔开的两个正整数 ai 和 bi,表示一开始就存 在一座连接岛 ai 和岛 bi 的桥。后面剩下的部分描述操作,该部分的第一行是一个正整数 q, 表示一共有 q 个操作,接下来的 q 行依次描述每个操作,操作的格式如上所述,以大写字母 Q 或B 开始,后面跟两个不超过 n 的正整数,字母与数字以及两个数字之间用空格隔开。 对于 20%的数据 n≤1000,q≤1000
对于 100%的数据 n≤100000,m≤n,q≤300000
Output
对于每个 Q x k 操作都要依次输出一行,其中包含一个整数,表 示所询问岛屿的编号。如果该岛屿不存在,则输出-1。
Sample Input
5 1
4 3 2 5 1
1 2
7
Q 3 2
Q 2 1
B 2 3
B 1 5
Q 2 1
Q 2 4
Q 2 3
Sample Output
-1
2
5
1
2
用并查集维护连通性,再用Treap维护第k大
#include <iostream> #include <cmath> #include <algorithm> #include <cstdio> #include <cstring> #include <string> #include <vector> #include <map> #include <functional> #include <cstdlib> #include <queue> #include <stack> #include <set> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define Rep(i,n) for(int i=0;i<n;i++) #define ForD(i,n) for(int i=n;i;i--) #define ForkD(i,k,n) for(int i=n;i>=k;i--) #define RepD(i,n) for(int i=n;i>=0;i--) #define Forp(x) for(int p=Pre[x];p;p=Next[p]) #define Forpiter(x) for(int &p=iter[x];p;p=Next[p]) #define Lson (o<<1) #define Rson ((o<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define MEMI(a) memset(a,127,sizeof(a)); #define MEMi(a) memset(a,128,sizeof(a)); #define INF (2139062143) #define F (20161119) #define ALL(x) (x).begin(),(x).end() #define pb push_back #define mp make_pair #define fi first #define se second #define vi vector<int> #define pi pair<int,int> #define SI(a) ((a).size()) #define Pri(a,n) for(int i=1;i<n;i++) cout<<a[i]<<' ';cout<<a <<endl; typedef long long ll; typedef unsigned long long ull; ll mul(ll a,ll b){return (a*b)%F;} ll add(ll a,ll b){return (a+b)%F;} ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;} void upd(ll &a,ll b){a=(a%F+b%F)%F;} int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN (100000*4) int n,m; struct treap{ ll rnd[MAXN],v[MAXN],w[MAXN]; int size[MAXN],l[MAXN],r[MAXN],cnt; void mem() { MEM(size) MEM(rnd) MEM(l) MEM(r) MEM(v) MEM(w) cnt=0; } void update(int x) { size[x]=size[l[x]]+size[r[x]]+w[x]; } void rturn(int &k) { int t=l[k];l[k]=r[t];r[t]=k;update(k);update(t);k=t; } void lturn(int &k) { int t=r[k];r[k]=l[t];l[t]=k;update(k);update(t);k=t; } void insert(int &x,ll rank,int y=0) { if(!x) { if (y) { x=y; l[x]=r[x]=0; rnd[x]=rand(); size[x]=w[x]; return; } x=++cnt; v[x]=rank; l[x]=r[x]=0; rnd[x]=rand();size[x]=w[x]=1; return ; } size[x]++; if(v[x]<rank) { insert(r[x],rank,y); if(rnd[r[x]]<rnd[x])lturn(x); } else if (v[x]>rank) { insert(l[x],rank,y); if(rnd[l[x]]<rnd[x]) rturn(x); }else w[x]++ ; } void unite(int &x,int y) { if (!y) return ; unite(x,l[y]); unite(x,r[y]); Rep(i,w[y]) insert(x,v[y],y); } void del(int &x,ll val) { if (!x) return ; if (v[x]==val) { if (w[x]>1) {--w[x]; --size[x]; return; } if (!l[x]||!r[x]) x=l[x]+r[x]; else if (rnd[l[x]]<rnd[r[x]]) rturn(x),del(x,val); else lturn(x),del(x,val); } else { --size[x]; if (val<v[x]) del(l[x],val); else del(r[x],val); } } // return the pointer int lower_bound(int x,ll rank) { int ans=-1; if (!x) return ans; if (v[x]<=rank) { ans=lower_bound(r[x],rank); if (ans==-1) ans=x; } else ans=lower_bound(l[x],rank); return ans; } int upper_bound(int x,ll rank) { int ans=-1; if (!x) return ans; if (v[x]>rank) { ans=upper_bound(l[x],rank); if (ans==-1) ans=x; } else ans=upper_bound(r[x],rank); return ans; } void pri(int x){ if (l[x]) pri(l[x]); cout<<v[x]<<' '; if (r[x]) pri(r[x]); } int get_rank(int x,ll val) { if (!x) return 0; if (v[x]==val) return size[l[x]]+1; else if (val<v[x]) return get_rank(l[x],val); else return get_rank(r[x],val)+size[l[x]]+w[x]; } int how_many_number_lower_than_x(int x,ll val) { if (!x) return 0; if (v[x]==val) return size[l[x]]; else if (val<v[x]) return how_many_number_lower_than_x(l[x],val); else return how_many_number_lower_than_x(r[x],val)+size[l[x]]+w[x]; } int get_kth(int x,int k) { if (!x) return -1; if (k<=size[l[x]]) return get_kth(l[x],k); else if (k<=size[l[x]]+w[x]) return x; else return get_kth(r[x],k-size[l[x]]-w[x]); } }T; int root[MAXN]; class bingchaji { public: int father[MAXN],n,cnt,sz[MAXN]; void mem(int _n) { n=cnt=_n; For(i,n) father[i]=i,sz[i]=1; } int getfather(int x) { if (father[x]==x) return x; return father[x]=getfather(father[x]); } void unite(int x,int y) { x=getfather(x); y=getfather(y); if (x^y) { --cnt; if (sz[x]>sz[y]) swap(x,y); father[x]=y; sz[y]+=sz[x]; T.unite(root[y],root[x]); } } bool same(int x,int y) { return getfather(x)==getfather(y); } }S; int a[MAXN]; int main() { // freopen("bzoj2733.in","r",stdin); n=read();m=read(); S.mem(n); For(i,n) a[i]=read(),T.insert(root[i],a[i]); For(i,m) { int x=read(),y=read(); S.unite(x,y); } int q=read(); For(i,q) { char opt[10];scanf("%s",opt); int x=read(),y=read(); switch (opt[0]) { case 'B':S.unite(x,y);break; case 'Q':printf("%d\n",T.get_kth(root[S.getfather(x)],y)); } } return 0; }
相关文章推荐
- BZOJ 2733: [HNOI2012]永无乡(treap + 启发式合并 + 并查集)
- 【BZOJ 2733】[HNOI2012]永无乡 启发式合并treap
- BZOJ 2733 HNOI2012 永无乡 Treap+启发式合并
- BZOJ 2733: [HNOI2012]永无乡 (Treap+启发式合并)
- BZOJ 2733: [HNOI2012]永无乡 启发式合并treap
- bzoj 2733: [HNOI2012]永无乡(线段树启发式合并)
- [并查集+启发式合并]BZOJ 2733——[HNOI2012]永无乡
- bzoj 2733 [HNOI2012]永无乡 splay启发式合并
- 【BZOJ 2733】 [HNOI2012]永无乡|Splay启发式合并
- BZOJ 2733 [HNOI2012] 永无乡 [splay+启发式合并做法]
- 【BZOJ 2733】【HNOI 2012】永无乡【treap启发式合并】
- BZOJ 2733: [HNOI2012]永无乡 [splay启发式合并]
- bzoj 2733: [HNOI2012]永无乡(线段树启发式合并)
- BZOJ 2733 HNOI 2012 永无乡 平衡树启发式合并
- BZOJ[2733][HNOI2012]永无乡 Splay启发式合并
- BZOJ 2733 [HNOI2012]永无乡 Treap + 并查集
- BZOJ 2733 [HNOI2012]永无乡 可持久化线段树合并
- 【模板】【bzoj2733】[HNOI2012]永无乡 Treap
- [BZOJ] 2733: [HNOI2012]永无乡 #线段树合并+并查集
- 【bzoj2733】[HNOI2012]永无乡 Treap启发式合并