【JZOJ5977】堆

Description

给定一个以1号节点为根的小根堆,要求支持两种操作。

  1. 添加一个带点权的叶子,将该权值往上更新,维护堆的性质。
  2. 查询一个点的权值。

Solution

注意到小根堆是自上往下单调递减的。
链剖+权值线段树,询问节点可以再链上找第k大。

Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define fo(i,j,k) for(int i=j;i<=k;++i)
#define fd(i,j,k) for(int i=j;i>=k;--i)
#define rep(i,x) for(int i=ls[x];i;i=nx[i])
using namespace std;
const int N=1e6+10,inf=1e9;
int to[N],nx[N],ls[N],num=0;
void link(int u,int v){
	to[++num]=v,nx[num]=ls[u],ls[u]=num;
}
int read(){
    char ch=' ';int t=0;
    for(;ch<'0' || ch>'9';ch=getchar());
    for(;ch>='0' && ch<='9';ch=getchar()) t=(t<<1)+(t<<3)+ch-48;
	return t;
}
int a[N],rt[N];
struct node{
	int l,r,s;
}tr[N<<4];
int fa[N],son[N],top[N],sz[N],dep[N],tot=0;
int pos[N];
int mx;
struct node2{
	int op,x;
}zu[N];
void pre(int x){
	sz[x]=1,son[x]=0;
	rep(i,x){
		int v=to[i];
		dep[v]=dep[x]+1;
		pre(v);
		if(sz[v]>sz[son[x]]) son[x]=v;
		sz[x]+=sz[v];
	}
}
void pre2(int x,int t){
	top[x]=t,pos[x]=dep[x]-dep[t]+1;
	if(son[x]) pre2(son[x],t);
	rep(i,x){
		int v=to[i];
		if(v==son[x]) continue;
		pre2(v,v);
	}
}
int find(int k,int v,int l=1,int r=mx){
	if(l==r) return l;
	int mid=(l+r)>>1;
	return tr[tr[v].l].s>=k?find(k,tr[v].l,l,mid):find(k-tr[tr[v].l].s,tr[v].r,mid+1,r);
}
int add(int x,int t,int v,int l=1,int r=mx){
	if(!v) v=++tot;
	tr[v].s+=t;
	if(l==r) return v;
	int mid=(l+r)>>1;
	x<=mid?tr[v].l=add(x,t,tr[v].l,l,mid):tr[v].r=add(x,t,tr[v].r,mid+1,r);
	return v;
}
void up(int x){
	rt[top[x]]=add(a[x],1,rt[top[x]]),x=top[x];
	int f1=fa[top[x]],p,q;
	while(f1 && (p=find(pos[f1],rt[top[f1]]))>(q=find(1,rt[x]))){
		add(p,-1,rt[top[f1]]),add(q,-1,rt[x]);
		add(q,1,rt[top[f1]]),add(p,1,rt[x]);
		x=top[f1],f1=fa[x];
	}
}
int main()
{
	freopen("heap.in","r",stdin);
	freopen("heap.out","w",stdout);
	int n=read(),q=read(),nn=n;
	fo(i,1,n){
		fa[i]=read(),a[i]=read();
		if(fa[i]) link(fa[i],i);
	}
	fo(i,1,q){
		zu[i].op=read(),zu[i].x=read();
		if(zu[i].op==1){
			fa[++n]=zu[i].x,a[n]=read(),zu[i].x=n;
			link(fa[n],n);
		}
	}
	pre(1);
	pre2(1,1);
	fo(i,1,n) mx=max(mx,a[i]);
	tot=0;
	fo(i,1,nn)
	rt[top[i]]=add(a[i],1,rt[top[i]]);
	fo(i,1,q){
		int x=zu[i].x;
		if(zu[i].op==1) up(x);
		else printf("%d\n",find(pos[x],rt[top[x]]));
		
	}
}

posted @ 2018-12-21 21:12  sadstone  阅读(48)  评论(0编辑  收藏  举报