• [题解]BZOJ3545&3551 Peaks


    题目描述

    (n)个点(m)条边的无向图,每个点和每条边都有一个权值,询问(u,x,k):问从(u)开始走边权不超过(x)的边所能到达的点中第(k)大的权值

    分析

    毕竟是在克鲁斯卡尔重构树的博客里面找到这题的,那么必然是要用到克鲁斯卡尔重构树的喽

    发现问题可以转化成求重构树上某一个点子树内的第(k)大,由于子树内的节点dfs序是连续的,可以用主席树来维护。

    代码

    细节还挺多的

    注意数组,还有主席树新建节点的时候记得复制信息

    #include<bits/stdc++.h>
    #define rep(X,A,B) for(int X=A;X<=B;X++)
    #define tep(X,A,B) for(int X=A;X>=B;X--)
    #define LL long long
    const int N=400010;
    const int M=500010;
    const int NN=400010;
    const int NNN=5000010;
    const int MX=30;
    using namespace std;
    
    struct nn{
    	int u,v,w;
    }E[M];
    
    int cmp(nn A,nn B){
    	return A.w<B.w;
    }
    
    int n,m,T;
    int a[N],hlp[N],len;
    int tmp=0,dfn[NN],pt[NN],lef[NN],rit[NN],val[NN];
    int tot=0,son[NNN][2],fa[NN][MX],pa[NN],dep[NN];
    int sum[NNN],rt[N];
    
    void READ(){
    	int u,v,w;
    	scanf("%d%d%d",&n,&m,&T);
    	rep(i,1,n)scanf("%d",&a[i]),hlp[i]=a[i];
    	//---
    	sort(hlp+1,hlp+n+1);
    	len=unique(hlp+1,hlp+n+1)-hlp-1;
    	rep(i,1,n)a[i]=lower_bound(hlp+1,hlp+len+1,a[i])-hlp;
    	//---
    	rep(i,1,m){
    		scanf("%d%d%d",&u,&v,&w);
    		E[i]=(nn){u,v,w};
    	}
    }//chked
    
    struct SegmentTree{
    	void BUILD(int x,int l,int r){
    		sum[x]=0;
    		if(l==r)return;
    		int mid=(l+r)>>1;
    		son[x][0]=++tot;BUILD(son[x][0],l,mid);
    		son[x][1]=++tot;BUILD(son[x][1],mid+1,r);
    	}//chked
    
    	void INS(int x,int las,int l,int r,int pos){
    		if(l==r){
    			sum[x]=sum[las]+1;//一开始写成sum[x]++挂了好久
    			return;
    		}
    		int	mid=(l+r)>>1;
    		if(pos<=mid){
    			son[x][0]=++tot;son[x][1]=son[las][1];
    			INS(son[x][0],son[las][0],l,mid,pos);
    		}
    		else{
    			son[x][1]=++tot;son[x][0]=son[las][0];
    			INS(son[x][1],son[las][1],mid+1,r,pos);
    		}
    		sum[x]=sum[son[x][0]]+sum[son[x][1]];
    	}
    
    	int QUE(int x,int las,int l,int r,int pos){
    		if(pos<=0)return -1;
    		if(l==r)return hlp[l];
    		if(sum[x]-sum[las]<pos)return -1;
    		int mid=(l+r)>>1;
    		int lf=sum[son[x][0]]-sum[son[las][0]];
    		if(lf>=pos)return QUE(son[x][0],son[las][0],l,mid,pos);
    		return QUE(son[x][1],son[las][1],mid+1,r,pos-lf);
    	}
    }sg;
    
    int GETFA(int x){
    	if(x!=pa[x])pa[x]=GETFA(pa[x]);
    	return pa[x];
    }
    
    void SEARCH(int x){
    	if(!x)return;
    	if(x<=n){
    		pt[++tmp]=x,dfn[x]=tmp,lef[x]=rit[x]=tmp;
    		return;
    	}
    	SEARCH(son[x][0]);
    	SEARCH(son[x][1]);
    	lef[x]=lef[son[x][0]];
    	rit[x]=rit[son[x][1]];
    }//chked
    
    void CHKFA(){
    	SEARCH(tot);
    	dep[tot]=0;
    	tep(x,tot,1)dep[x]=dep[fa[x][0]]+1;
    	rep(i,1,20){
    		rep(x,1,tot){
    			if((1<<i)>=dep[x])continue;
    			fa[x][i]=fa[fa[x][i-1]][i-1];
    		}
    	}
    }
    
    void INIT(){
    	sort(E+1,E+m+1,cmp);
    	rep(i,1,n)pa[i]=i;
    	tot=n;
    	//---
    	rep(i,1,m){
    		int fu=GETFA(E[i].u),fv=GETFA(E[i].v);
    		if(fu==fv)continue;
    		tot++;
    		val[tot]=E[i].w;
    		fa[fu][0]=fa[fv][0]=tot;
    		son[tot][0]=fu;son[tot][1]=fv;
    		pa[fu]=pa[fv]=pa[tot]=tot;
    	}
    	//---
    	CHKFA();
    	rep(i,0,tot)son[i][0]=son[i][1]=0;
    	tot=0;
    
    	rt[0]=1;sg.BUILD(1,1,len);
    	rep(i,1,n)rt[i]=++tot,sg.INS(rt[i],rt[i-1],1,len,a[pt[i]]);
    	
    }
    int GET(int x,int mx){
    	tep(i,20,0){
    		if((1<<i)>=dep[x])continue;
    		if(val[fa[x][i]]<=mx)x=fa[x][i];
    	}
    	return x;
    }
    
    void SOLVE(){
    	int u,x,K;
    	scanf("%d%d%d",&u,&x,&K);
    	int now=GET(u,x);
    	int L=lef[now],R=rit[now];
    	printf("%d
    ",sg.QUE(rt[R],rt[L-1],1,len,sum[rt[R]]-sum[rt[L-1]]-K+1));
    }
    
    int main(){
    	READ();
    	INIT();
    	while(T--)SOLVE();
    	return 0;
    }
    
  • 相关阅读:
    启用Netlogon debug,查看服务器验证瓶颈
    Windows Server 2016调整网卡顺序
    AD用户添加到组
    客户端查看/修改所属站点
    OpenCV相关库
    《塔木德》笔记
    《如何阅读一本书》笔记
    《创业维艰》笔记
    《社会心理学》笔记
    《智能商业》笔记
  • 原文地址:https://www.cnblogs.com/SCL123/p/11761716.html
Copyright © 2020-2023  润新知