bzoj3551 [ONTAK2010]Peaks加强版 kruskal重构树

最大边最小,就是最小生成树,可以考虑用主席树维护father数组,但不能遍历子集查找

然后就只能牺牲一部分空间时间来多存一些东西

多存的就是边值大小顺序,本来以为是用主席树排边值,结果由于此题有2种数据(边值、点值)要排,所以每加一个边维护点值排序空间是不对的

然后就按照边重构一棵树,尽量利用以前的结果,由于主席树类似桶排,利于合并,所以就直接指针指过去就可以了

就是在原来并查集合并的基础上,让边可持久化,用边的大小调整选用的集合

这样一个边值的一个块就在一个子树里了

然后就是子树第K大


码:

#include<bits/stdc++.h>
using namespace std;
int fu[500005],f[200005][25],qian[200005],cnt,sz[200005*20],ch[200005*20][2],i,lin[500005],tot,co[200005],a,b,v[500005],m,q,rt[200005],c,lrt[200005],last,ans,n,k,vv,x;
map<int,int>ma;
vector<int>xia[200005];
struct la
{
	int a,b,v;
}B[500005];
bool cmp(la a,la b)
{
	return a.v<b.v;
}
int zhao(int o)
{
	if(fu[o]!=o)fu[o]=zhao(fu[o]);
	return fu[o];
}
void dfs(int o)
{
	int i;
	for(i=1;i<=20;i++)
	f[o][i]=f[f[o][i-1]][i-1];
	for(i=0;i<xia[o].size();i++)
	{
		dfs(xia[o][i]);		
	}	
}
void up(int o)
{
	sz[o]=sz[ch[o][0]]+sz[ch[o][1]];
}
void jia(int o,int last,int l,int r)
{
if(l==r)
{
	sz[o]=sz[last]+1;	
return ;	
}	

int mid=(l+r)>>1;
	if(a<=mid){
		ch[o][0]=++cnt;
	    ch[o][1]=ch[last][1];
	jia(ch[o][0],ch[last][0],l,mid);	
	}
	if(b>mid)
	{
		ch[o][0]=ch[last][0];
	    ch[o][1]=++cnt;
	jia(ch[o][1],ch[last][1],mid+1,r);
	}
	up(o);	
}
void dfs2(int o)
{
int i;
a=b=ma[v[o]];
rt[o]=++cnt;
qian[o]=last;
jia(rt[o],last,1,n);
last=rt[o];
for(i=0;i<xia[o].size();i++)
{
int nd=xia[o][i];	
dfs2(nd);
}	
lrt[o]=last;
}
void cha(int o,int last,int l,int r)
{
if(sz[o]-sz[last]<k)return;
if(l==r)
{c=l;return ;}
int mid=(l+r)>>1;
if(sz[ch[o][1]]-sz[ch[last][1]]>=k)cha(ch[o][1],ch[last][1],mid+1,r);
else k-=sz[ch[o][1]]-sz[ch[last][1]],cha(ch[o][0],ch[last][0],l,mid);			
}
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int main()
{
//freopen("la.in","r",stdin);
	scanf("%d%d%d",&n,&m,&q);for(i=1;i<=n*3;i++)fu[i]=i,v[i]=-1;
	for(i=1;i<=n;i++)v[i]=read(),lin[i]=v[i];

	for(i=1;i<=m;i++){
	
	B[i].a=read();
	B[i].b=read();
	B[i].v=read();	
	}
 
   tot=n;lin[n+1]=-1;
	sort(lin+1,lin+2+n);
	n++;
	for(i=1;i<=n;i++)
	ma[lin[i]]=i;
sort(B+1,B+1+m,cmp);
    for(i=1;i<=m;i++)
	{
		int f1=zhao(B[i].a);
		int f2=zhao(B[i].b);
		if(f1==f2)continue;
		++tot;
		f[f1][0]=tot;
		f[f2][0]=tot;
		fu[f1]=tot;
		fu[f2]=tot;
		xia[tot].push_back(f1);
		xia[tot].push_back(f2);
		co[tot]=B[i].v;		
	}	
	dfs(tot);
    dfs2(tot);
	lrt[0]=last;
	while(q--)
	{
    x=read();vv=read();k=read();
    if(ans!=-1)x^=ans,vv^=ans,k^=ans;
	for(i=20;i>=0;i--)
	if(f[x][i]&&co[f[x][i]]<=vv)x=f[x][i];
	c=1;	
	cha(lrt[x],qian[x],1,n);
	if(c==1){
	ans=-1;	
	printf("-1\n");
	}else
{ans=lin[c];
	printf("%d\n",ans);
}
	}	
}


猜你喜欢

转载自blog.csdn.net/haobang866/article/details/79274743