zoukankan      html  css  js  c++  java
  • [HNOI2012] 永无乡

    前言

    没啥好说的,练板子水博客

    题目

    洛谷

    讲解

    联通性并查集维护,合并两个区间以及回答询问有两个做法。

    做法1 平衡树

    直接启发式暴力单点插入即可。

    做法2 线段树合并

    当然是权值线段树,回答询问时直接在线段树上二分就行。

    代码

    C++14 O2

    FHQ Treap 649ms 3.16MB
    //12252024832524
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define TT template<typename T>
    using namespace std; 
    
    typedef long long LL;
    const int MAXN = 100005;
    const int MOD = 1e9 + 7;
    int n,m;
    
    LL Read()
    {
    	LL x = 0,f = 1;char c = getchar();
    	while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
    	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
    	return x * f;
    }
    TT void Put1(T x)
    {
    	if(x > 9) Put1(x/10);
    	putchar(x%10^48);
    }
    TT void Put(T x,char c = -1)
    {
    	if(x < 0) putchar('-'),x = -x;
    	Put1(x); if(c >= 0) putchar(c);
    }
    TT T Max(T x,T y){return x > y ? x : y;}
    TT T Min(T x,T y){return x < y ? x : y;}
    TT T Abs(T x){return x < 0 ? -x : x;}
    
    struct FHQ_Treap
    {
    	int l,r,f,siz,val,ID,rd;
    }t[MAXN];
    void up(int x){t[x].siz = t[t[x].l].siz + t[t[x].r].siz + 1;}
    void split(int now,int val,int &x,int &y)
    {
    	if(!now) {x = y = 0;return;}
    	else
    	{
    		if(t[now].val <= val) 
    		{
    			x = now;
    			split(t[now].r,val,t[now].r,y);
    			t[t[now].r].f = x;
    		}
    		else
    		{
    			y = now;
    			split(t[now].l,val,x,t[now].l);
    			t[t[now].l].f = y;
    		}
    		up(now);//now!!! not x!!!
    	}
    }
    int mge(int x,int y)
    {
    	if(!x || !y) return x|y;
    	if(t[x].rd < t[y].rd)
    	{
    		t[x].r = mge(t[x].r,y); up(x);
    		t[t[x].r].f = x;
    		return x;
    	}
    	else
    	{
    		t[y].l = mge(x,t[y].l); up(y);
    		t[t[y].l].f = y;
    		return y;
    	}
    }
    int qval(int now,int rk)
    {
    	while(t[now].f) now = t[now].f; 
    	if(t[now].siz < rk) return -1;
    	while(1)
    	{
    		if(t[t[now].l].siz + 1 == rk) return t[now].ID;
    		if(t[t[now].l].siz >= rk) now = t[now].l;
    		else rk -= t[t[now].l].siz+1,now = t[now].r; 
    	}
    }
    int Rand(){return (1ll * rand() * rand() * rand() + rand()) % MOD;}
    void unionSet(int u,int v)
    {
    	int x,y;
    	while(t[u].f) u = t[u].f;
    	while(t[v].f) v = t[v].f;
    	if(u == v) return;
    	if(t[u].siz < t[v].siz) swap(u,v);
    	int S = t[v].siz;
    	for(int i = 1;i <= S;++ i)
    	{
    		int R = v;
    		v = mge(t[R].l,t[R].r);
    		t[R].l = t[R].r = 0; t[R].siz = 1;
    		split(u,t[R].val-1,x,y);
    		u = mge(mge(x,R),y);
    	}
    }
    
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	srand(42523);
    	n = Read(); m = Read();
    	for(int i = 1;i <= n;++ i) t[i] = {0,0,0,1,(int)Read(),i,Rand()};//l,r,f,siz,val,ID,rd
    	for(int i = 1;i <= m;++ i) unionSet(Read(),Read());
    	for(int T = Read(); T ;-- T)
    	{
    		char c = getchar();
    		while(c != 'B' && c != 'Q') c = getchar();
    		if(c == 'B') unionSet(Read(),Read());
    		else
    		{
    			int ID = Read();
    			Put(qval(ID,Read()),'
    ');
    		}
    	}
    	return 0;
    }
    
    线段树合并 452ms 34.12MB
    //12252024832524
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define TT template<typename T>
    using namespace std; 
    
    typedef long long LL;
    const int MAXN = 100005;
    int n,m;
    
    LL Read()
    {
    	LL x = 0,f = 1;char c = getchar();
    	while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
    	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
    	return x * f;
    }
    TT void Put1(T x)
    {
    	if(x > 9) Put1(x/10);
    	putchar(x%10^48);
    }
    TT void Put(T x,char c = -1)
    {
    	if(x < 0) putchar('-'),x = -x;
    	Put1(x); if(c >= 0) putchar(c);
    }
    TT T Max(T x,T y){return x > y ? x : y;}
    TT T Min(T x,T y){return x < y ? x : y;}
    TT T Abs(T x){return x < 0 ? -x : x;}
    
    int f[MAXN];
    int findSet(int x)
    {
    	if(x ^ f[x]) f[x] = findSet(f[x]);
    	return f[x];
    }
    int rt[MAXN];
    int ch[MAXN<<5][2],tot,siz[MAXN<<5],ans[MAXN<<5];
    void up(int x)
    {
    	if(!x) return;
    	siz[x] = siz[ch[x][0]] + siz[ch[x][1]];
    }
    void Build(int &x,int l,int r,int pos,int val)
    {
    	if(!x) x = ++tot;
    	if(l == r) {siz[x] = 1;ans[x] = val;return;}
    	int mid = (l+r) >> 1;
    	if(pos <= mid) Build(ch[x][0],l,mid,pos,val);
    	else Build(ch[x][1],mid+1,r,pos,val);
    	up(x);
    }
    int mge(int x,int y)
    {
    	if(!x || !y) return x|y;
    	ch[x][0] = mge(ch[x][0],ch[y][0]);
    	ch[x][1] = mge(ch[x][1],ch[y][1]);
    	siz[x] += siz[y];
    	ans[x] = Max(ans[x],ans[y]);
    	return x;
    }
    void unionSet(int u,int v)
    {
    	u = findSet(u); v = findSet(v);
    	if(u == v) return;
    	if(u > v) swap(u,v); f[v] = u;
    	rt[u] = mge(rt[u],rt[v]);
    }
    void Query(int x,int l,int r,int rk)
    {
    	if(rk > siz[x]){Put(-1,'
    ');return;}
    	if(l == r){Put(ans[x],'
    ');return;}
    	int mid = (l+r) >> 1;
    	if(siz[ch[x][0]] >= rk) Query(ch[x][0],l,mid,rk);
    	else Query(ch[x][1],mid+1,r,rk-siz[ch[x][0]]);
    }
    
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	n = Read(); m = Read();
    	for(int i = 1;i <= n;++ i) Build(rt[i],1,n,Read(),i),f[i] = i;
    	for(int i = 1;i <= m;++ i) unionSet(Read(),Read());
    	for(int T = Read(); T ;-- T)
    	{
    		char c = getchar();
    		while(c != 'B' && c != 'Q') c = getchar();
    		int x = Read();
    		if(c == 'Q') Query(rt[findSet(x)],1,n,Read());
    		else unionSet(x,Read());
    	}
    	return 0;
    }
    
  • 相关阅读:
    UGUI组件之Scrollbar 卷动条组件简单笔记
    在VerilogHDL中调用VHDL的模块
    jQuery表格删除功能
    offset方法与position方法
    小火箭返回顶部案例
    jQuery弹幕效果
    用jQuery写微博发布案例
    用jQuery写城市选择案例
    jquery创建与添加节点
    jQuery停止动画详情
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/15233164.html
Copyright © 2011-2022 走看看