洛谷 P4197 Peaks & P7834 [ONTAK2010] Peaks 加强版 题解--zhengjun

思路

模拟赛的题,有点板。

直接建出原图的 Kruscal 重构树,然后发现询问变成了一个子树内区间第 K 大。

直接转化到序列上然后主席树即可。

代码-P4197 Peaks

#include<bits/stdc++.h>
using namespace std;typedef long long ll;const int N=1e5+10,M=5e5+10,T=N*2,K=log2(T)+2,P=1e7;
int n,m,q,lg,a[N],b[M],v[M],root[M],cnt,f[K][T],l[T],r[T],tot,pos[N],dfn[N];vector<int>e[T];
void add(int u,int v){e[u].push_back(v);}
struct edges{int u,v,w;}c[M];struct tree{int ls,rs,siz;}t[P];
int find(int x){return f[0][x]==x?x:f[0][x]=find(f[0][x]);}
void update(int cur,int &rt,int l=1,int r=b[0]){
	t[++cnt]=t[rt];rt=cnt;t[rt].siz++;if(l==r)return;int mid=(l+r)>>1;
	cur<=mid?update(cur,t[rt].ls,l,mid):update(cur,t[rt].rs,mid+1,r);
}
int query(int rt1,int rt2,int k,int l=1,int r=b[0]){
	if(l==r)return k&&k<=t[rt2].siz-t[rt1].siz?b[l]:-1;int mid=(l+r)>>1;
	if(k<=t[t[rt2].rs].siz-t[t[rt1].rs].siz)return query(t[rt1].rs,t[rt2].rs,k,mid+1,r);
	return query(t[rt1].ls,t[rt2].ls,k-(t[t[rt2].rs].siz-t[t[rt1].rs].siz),l,mid);
}
void dfs1(int u){if(u<=n)pos[dfn[u]=++pos[0]]=u;for(int v:e[u])f[0][v]=u,dfs1(v);}
void dfs2(int u){if(u<=n)l[u]=r[u]=dfn[u];for(int v:e[u])dfs2(v),l[u]=min(l[u],l[v]),r[u]=max(r[u],r[v]);}
void init(){for(int i=1;(1<<i)<=tot;i++)for(int j=1;j<=tot;j++)f[i][j]=f[i-1][f[i-1][j]];}
int main(){
	scanf("%d%d%d",&n,&m,&q);for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i];sort(b+1,b+1+n);
	memset(l,0x3f,sizeof l);b[0]=unique(b+1,b+1+n)-b-1;for(int i=1;i<T;i++)f[0][i]=i;
	for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+1+b[0],a[i])-b;
	for(int i=1;i<=m;i++)scanf("%d%d%d",&c[i].u,&c[i].v,&c[i].w);tot=n;
	sort(c+1,c+1+m,[](edges x,edges y){return x.w<y.w;});for(int i=1;i<=m;i++)if(find(c[i].u)^find(c[i].v)){
		add(tot+1,find(c[i].u)),add(tot+1,find(c[i].v)),f[0][find(c[i].u)]=f[0][find(c[i].v)]=++tot,v[tot]=c[i].w;
	}for(int i=1;i<=n;i++)if(find(i)<=tot)add(tot+1,find(i)),f[0][find(i)]=tot+1;
	lg=log2(++tot);dfs1(tot);dfs2(tot);init();v[tot]=2e9;
	for(int i=1;i<=n;i++)update(a[pos[i]],root[i]=root[i-1]);for(int i=1,las=-1,u,x,k;i<=q;i++){
		scanf("%d%d%d",&u,&x,&k);for(int j=lg;~j;j--)
			if(f[j][u]&&v[f[j][u]]<=x)u=f[j][u];printf("%d\n",las=query(root[l[u]-1],root[r[u]],k));
	}return 0;
}

代码-P7834 [ONTAK2010] Peaks 加强版

#include<bits/stdc++.h>
using namespace std;typedef long long ll;const int N=1e5+10,M=5e5+10,T=N*2,K=log2(T)+2,P=1e7;
int n,m,q,lg,a[N],b[M],v[M],root[M],cnt,f[K][T],l[T],r[T],tot,pos[N],dfn[N];vector<int>e[T];
void add(int u,int v){e[u].push_back(v);}
struct edges{int u,v,w;}c[M];struct tree{int ls,rs,siz;}t[P];
int find(int x){return f[0][x]==x?x:f[0][x]=find(f[0][x]);}
void update(int cur,int &rt,int l=1,int r=b[0]){
	t[++cnt]=t[rt];rt=cnt;t[rt].siz++;if(l==r)return;int mid=(l+r)>>1;
	cur<=mid?update(cur,t[rt].ls,l,mid):update(cur,t[rt].rs,mid+1,r);
}
int query(int rt1,int rt2,int k,int l=1,int r=b[0]){
	if(l==r)return k&&k<=t[rt2].siz-t[rt1].siz?b[l]:-1;int mid=(l+r)>>1;
	if(k<=t[t[rt2].rs].siz-t[t[rt1].rs].siz)return query(t[rt1].rs,t[rt2].rs,k,mid+1,r);
	return query(t[rt1].ls,t[rt2].ls,k-(t[t[rt2].rs].siz-t[t[rt1].rs].siz),l,mid);
}
void dfs1(int u){if(u<=n)pos[dfn[u]=++pos[0]]=u;for(int v:e[u])f[0][v]=u,dfs1(v);}
void dfs2(int u){if(u<=n)l[u]=r[u]=dfn[u];for(int v:e[u])dfs2(v),l[u]=min(l[u],l[v]),r[u]=max(r[u],r[v]);}
void init(){for(int i=1;(1<<i)<=tot;i++)for(int j=1;j<=tot;j++)f[i][j]=f[i-1][f[i-1][j]];}
int main(){
	scanf("%d%d%d",&n,&m,&q);for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i];sort(b+1,b+1+n);
	memset(l,0x3f,sizeof l);b[0]=unique(b+1,b+1+n)-b-1;for(int i=1;i<T;i++)f[0][i]=i;
	for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+1+b[0],a[i])-b;
	for(int i=1;i<=m;i++)scanf("%d%d%d",&c[i].u,&c[i].v,&c[i].w);tot=n;
	sort(c+1,c+1+m,[](edges x,edges y){return x.w<y.w;});for(int i=1;i<=m;i++)if(find(c[i].u)^find(c[i].v)){
		add(tot+1,find(c[i].u)),add(tot+1,find(c[i].v)),f[0][find(c[i].u)]=f[0][find(c[i].v)]=++tot,v[tot]=c[i].w;
	}for(int i=1;i<=n;i++)if(find(i)<=tot)add(tot+1,find(i)),f[0][find(i)]=tot+1;
	lg=log2(++tot);dfs1(tot);dfs2(tot);init();v[tot]=0x7fffffff;
	for(int i=1;i<=n;i++)update(a[pos[i]],root[i]=root[i-1]);for(int i=1,las=-1,u,x,k;i<=q;i++){
		scanf("%d%d%d",&u,&x,&k);if(las==-1)las=0; 
		if(las!=-1)u^=las,u%=n,u++,x^=las,k^=las,k%=n,k++;
		for(int j=lg;~j;j--)if(f[j][u]&&v[f[j][u]]<=x)u=f[j][u];
		if(l[u]<=r[u])printf("%d\n",las=query(root[l[u]-1],root[r[u]],k));else puts("-1"),las=-1;
	}return 0;
}
posted @ 2022-07-04 19:24  A_zjzj  阅读(37)  评论(0编辑  收藏  举报