zoukankan      html  css  js  c++  java
  • BZOJ 3123: [Sdoi2013]森林 [主席树启发式合并]

    3123: [Sdoi2013]森林

    题意:一个森林,加边,询问路径上k小值。保证任意时刻是森林


    LCT没法搞,树上kth肯定要用树上主席树
    加边?启发式合并就好了,小的树dfs重建一下
    注意

    1. 测试点编号不是数据组数!!!
    2. 加边的时候要更新邻接链表啊,并且fa要清空
    3. 并查集维护size一定初始化1

    好了现在我要填报名表了
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    #define lc(x) t[x].l
    #define rc(x) t[x].r
    const int N=1e5+5, M=2e5+5;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    int n, m, Q, a[N], u, v, k, mp[N]; char s[5];
    namespace ufs{
    	int fa[N], size[N];
    	int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}
    } using ufs::size; using ufs::find;
    
    struct edge{int v,ne;}e[M];
    int cnt, h[N];
    inline void ins(int u, int v) {
    	e[++cnt]=(edge){v, h[u]}; h[u]=cnt;
    	e[++cnt]=(edge){u, h[v]}; h[v]=cnt;
    }
    int vis[N], fa[N][18], deep[N];
    int lca(int x, int y) {
    	if(deep[x]<deep[y]) swap(x, y);
    	int bin=deep[x]-deep[y];
    	for(int i=0; i<17; i++) if((1<<i)&bin) x=fa[x][i];
    	if(x==y) return x;
    	for(int i=16; i>=0; i--) 
    		if(fa[x][i] != fa[y][i]) x=fa[x][i], y=fa[y][i];
    	return fa[x][0];
    }
    
    
    struct ChairTree{
    	struct meow{int l,r,size;}t[N*85];
    	int sz, root[N];
    
    	void insert(int &x, int l, int r, int p) {
    		t[++sz]=t[x]; x=sz;
    		t[x].size++;
    		if(l==r) return;
    		int mid=(l+r)>>1;
    		if(p<=mid) insert(lc(x), l, mid, p);
    		else insert(rc(x), mid+1, r, p);
    	}
    	void build(int u) { //printf("build %d %d
    ",u,fa[u][0]);
    		vis[u]=1;
    		for(int i=1; (1<<i)<=deep[u]; i++)
    			fa[u][i] = fa[ fa[u][i-1] ][i-1];
    		root[u] = root[fa[u][0]];
    		insert(root[u], 1, *mp, a[u]);
    		for(int i=h[u];i;i=e[i].ne) 
    			if(e[i].v != fa[u][0]) {
    				fa[e[i].v][0]=u; deep[e[i].v]=deep[u]+1;
    				build(e[i].v);
    			}
    	}
    
    	int query(int u, int v, int k) {
    		int f=lca(u,v), g=fa[f][0];  
    		int x=root[u], y=root[v], l=1, r=*mp; f=root[f]; g=root[g];
    		while(l!=r) {
    			int lsize = t[lc(x)].size + t[lc(y)].size - t[lc(f)].size - t[lc(g)].size;
    			int mid=(l+r)>>1; 
    			if(k<=lsize) x=lc(x), y=lc(y), f=lc(f), g=lc(g), r=mid;
    			else x=rc(x), y=rc(y), f=rc(f), g=rc(g), l=mid+1, k-=lsize;
    		}
    		return l;
    	}
    
    	void rebuild(int u) {
    		for(int i=1; i<17; i++) 
    			fa[u][i] = fa[ fa[u][i-1] ][i-1];
    		root[u] = root[fa[u][0]];
    		insert(root[u], 1, *mp, a[u]);
    		for(int i=h[u];i;i=e[i].ne) 
    			if(e[i].v != fa[u][0]) {
    				fa[e[i].v][0]=u; deep[e[i].v]=deep[u]+1;
    				rebuild(e[i].v);
    			}
    	}
    	void Link(int u, int v) { 
    		int x=find(u), y=find(v);
    		if(size[x]<size[y]) swap(x, y), swap(u, v);
    		ufs::fa[y]=x; size[x]+=size[y];
    		ins(u, v);
    		fa[v][0]=u; deep[v]=deep[u]+1;
    		rebuild(v);
    	}
    }C;
    
    
    int candy;
    int main() {
    	freopen("in","r",stdin);
    
    	int T=read(); T+=2333;
    
    	n=read(); m=read(); Q=read();
    	for(int i=1; i<=n; i++) a[i]=mp[i]=read(), ufs::fa[i]=i, size[i]=1;
    	sort(mp+1, mp+1+n); mp[0]=unique(mp+1, mp+1+n)-mp-1;
    	for(int i=1; i<=n; i++) a[i] = lower_bound(mp+1, mp+1+*mp, a[i])-mp;
    
    	for(int i=1; i<=m; i++) {
    		u=read(), v=read();
    		ins(u,v);
    		u=find(u); v=find(v); 
    		ufs::fa[v]=u; size[u]+=size[v];
    	}
    	for(int i=1; i<=n; i++) if(!vis[i]) C.build(i);
    
    	int ans=0;
    //candy=1;
    	for(int i=1; i<=Q; i++) {
    		scanf("%s",s);
    		if(candy) u=read(), v=read();
    		else u=read()^ans, v=read()^ans;
    		if(s[0]=='Q') {
    			if(candy) k=read();
    			else k=read()^ans;
    			ans = mp[C.query(u, v, k)];
    			printf("%d
    ", ans);
    		}else C.Link(u, v);
    	}
    }
    
    
    
    
  • 相关阅读:
    C#中调用DTS
    经典问题:向setTimeout传递函数参数
    C#.NET 中的类型转换
    SQL语句导入导出大全 (转载)
    js脚本defer的作用
    [转]使用 Java API 处理 WebSphere MQ 大消息
    WideCharToMultiByte 宽字节转换为多字节
    [原].NET数据库开发中请注意区域时间格式
    输出页眉和页脚的简单HTTP模块实践
    浅析ASP.NET HTTP Module
  • 原文地址:https://www.cnblogs.com/candy99/p/6623062.html
Copyright © 2011-2022 走看看