zoukankan      html  css  js  c++  java
  • BZOJ 3551: [ONTAK2010]Peaks加强版 [Kruskal重构树 dfs序 主席树]

    3551: [ONTAK2010]Peaks加强版

    题意:带权图,多组询问与一个点通过边权(le lim)的边连通的点中点权k大值,强制在线


    PoPoQQQ大爷题解传送门


    说一下感受:
    容易发现一定选最小生成树上的边,然后用到了一个神奇的东西

    Kruskal重构树

    • 进行Kruskal过程中,每条边用一个点代替,左右儿子分别是连的两个点的当前的父亲
      这样就形成了一棵树,叶子都是原图上的点,其他都是原图上的边
    • 深度越小的点对应的边权值越大
    • 两点路径上的权值不变
    • 这样的话,与一个点通过权值(le lim)的边连通,就是这个点权值(le lim)的父亲对应的子树中的点
      对dfs序建主席树就行了


      实现上我只将原图中的点加入了dfs序


      该死离散化写错了WA了半小时
    #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=2e5+5, M=5e5+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, val[N], tot, u, lim, k, mp[N];
    struct meow{
    	int u,v,w;
    	bool operator <(const meow &r) const{return w<r.w;}
    }a[M];
    namespace ufs{
    	int fa[N];
    	int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}
    }
    struct edge{int v,ne;}e[N<<1];
    int cnt, h[N];
    inline void ins(int u, int v) {
    	e[++cnt]=(edge){v, h[u]}; h[u]=cnt;
    }
    void Kruskal() {
    	using ufs::fa; using ufs::find;
    	sort(a+1, a+1+m);
    	int cnt=0;
    	for(int i=1; i<=m; i++) { 
    		int u=a[i].u, v=a[i].v, w=a[i].w;
    		int x=find(u), y=find(v);
    		if(x==y) continue;
    
    		val[++tot]=w; //printf("hey %d %d  %d  %d
    ",x,y,tot,val[tot]);
    		ins(tot, x); ins(tot, y);
    		fa[x]=fa[y]=fa[tot]=tot;
    		if(++cnt == n-1) break;
    	}
    }
    
    int deep[N], dfc, ver[N], L[N], R[N];
    int fa[N][20];
    void dfs(int u) { //printf("dfs %d %d
    ",u,val[u]);
    	if(u<=n) ver[++dfc]=u;
    	L[u]=dfc;
    	for(int i=1; (1<<i)<=deep[u]; i++) 
    		fa[u][i] = fa[ fa[u][i-1] ][i-1];
    	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;
    			dfs(e[i].v);
    		}
    	R[u]=dfc;
    }
    
    struct ChairTree{
    	struct meow{int l,r,size;}t[N*30];
    	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(t[x].l, l, mid, p);
    		else insert(t[x].r, mid+1, r, p);
    	}
    	void build() { 
    		for(int i=1; i<=n; i++) root[i]=root[i-1], insert(root[i], 1, *mp, val[ver[i]]);// printf("%d ",ver[i]);puts("");
    	}
    	int kth(int x, int y, int k) { //printf("kth %d %d %d
    ",x,y,k);
    		x=root[x]; y=root[y];
    		int all = t[y].size-t[x].size; //printf("xy %d %d %d
    ",x,y,all);
    		if(k>all) return -1;
    		k = all-k+1;
    		int l=1, r=*mp;
    		while(l!=r) {
    			int lsize = t[lc(y)].size - t[lc(x)].size, mid=(l+r)>>1;
    			if(k<=lsize) x=lc(x), y=lc(y), r=mid;
    			else x=rc(x), y=rc(y), l=mid+1, k-=lsize;
    		}
    		return l;
    	}
    }C;
    int main() {
    	freopen("in","r",stdin);
    	n=read(); m=read(); Q=read(); tot=n;
    	for(int i=1; i<=n; i++) val[i]=mp[i]=read(), ufs::fa[i]=i;
    	val[0]=1e9+5;
    	for(int i=1; i<=m; i++) a[i].u=read(), a[i].v=read(), a[i].w=read();
    	Kruskal();
    	dfs(tot);
    	sort(mp+1, mp+1+n); mp[0]=unique(mp+1, mp+1+n)-mp-1;
    	for(int i=1; i<=n; i++) val[i] = lower_bound(mp+1, mp+1+mp[0], val[i])-mp;
    	C.build();
    	int ans=0;
    	for(int i=1; i<=Q; i++) {
    		if(ans==-1) ans=0;
    		u=read()^ans, lim=read()^ans, k=read()^ans;
    		//u=read();lim=read();k=read();
    		for(int i=16; i>=0; i--) if(val[fa[u][i]]<=lim) u=fa[u][i];
    		ans = C.kth(L[u], R[u], k);
    		if(ans!=-1) ans=mp[ans];
    		printf("%d
    ",ans);
    	}
    }
    
  • 相关阅读:
    java String 转Json报错 java.lang.NoClassDefFoundError: org/apache/commons/lang/exception/NestableRuntim
    Idea 进行断点调试的 快捷键
    spring AOP的使用步骤
    AOP的定义和原理
    SpringBoot入门篇--使用IDEA创建一个SpringBoot项目
    详解CI、CD相关概念
    intellij idea 的全局搜索快捷键方法
    面向对象之工厂模式与构造函数模式的区别
    冒泡排序和快速排序
    java里的数组和list分别在什么情况下使用?
  • 原文地址:https://www.cnblogs.com/candy99/p/6623650.html
Copyright © 2011-2022 走看看