Bzoj3551:[ONTAK2010]Peaks加强版:Kruskal+主席树

题目链接:[ONTAK2010]Peaks加强版

做一遍Kruscal,对于要合并联通块的两个点x,y新建节点z令fa[x]=fa[y]=z,并且节点z的权值为这条边的边权

那么我们对于一个询问只需要倍增出最后一个权值>x的节点,这颗子树就是我们要找到的联通块

主席树维护即可

#include
#include
#include
#include
using namespace std;
const int maxn=300010;
const int maxN=5000000;
const int inf=0x7fffffff/2-1;
int n,m,f[maxn],tmp[maxn],a[maxn];
struct edge{int a,b,w;}e[maxn<<1];
int lson[maxN],rson[maxN],T[maxn];
int tot=0,cnt=0,N=0,totr=0,ind=0;
int s[maxN],fa[maxn][20],st[maxn];
int h[maxn],ed[maxn],dep[maxn],Q;
struct edges{int to,next;}G[maxn<<2];

int read(){
    int x=0; char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x;
}

int getpos(int x){
	int l=1,r=N,ret=-1;
	while (l<=r){
		int mid=(l+r)>>1;
		if (tmp[mid]>x) r=mid-1;
		else l=mid+1,ret=mid;
	}return ret;
}

bool cmp(const edge &a,const edge &b){
	return a.w>1;
	if (pos<=mid) rson[rt]=rson[pre],ins(lson[pre],lson[rt],l,mid,pos);
	else lson[rt]=lson[pre],ins(rson[pre],rson[rt],mid+1,r,pos);
}

void dfs(int x){
	dep[x]=dep[fa[x][0]]+1;
	st[x]=++ind;
	for (int i=1;i<=18;++i){
		if (dep[x]<(1<>1,sum=s[rson[rt]]-s[rson[pre]];
	if (sum>=k) return query(rson[pre],rson[rt],mid+1,r,k);
	else return query(lson[pre],lson[rt],l,mid,k-sum);
}

int main(){
	n=read(); m=read(); Q=read(); cnt=n;
	for (int i=1;i<=n;++i) a[i]=read(),tmp[i]=a[i];
	sort(tmp+1,tmp+n+1); tmp[0]=-inf;
	for (int i=1;i<=n;++i) if (tmp[i]!=tmp[i-1]) tmp[++N]=tmp[i];
	for (int i=1;i<=n;++i) a[i]=getpos(a[i]);
	for (int i=1;i<=m;++i)
		e[i].a=read(),e[i].b=read(),e[i].w=read();
	sort(e+1,e+m+1,cmp); 
	for (int i=1;i=0;--j){
			if (dep[rt]<(1<


你可能感兴趣的:(OI,可持久化线段树,生成树)