1. 程式人生 > 其它 >#線段樹,樹狀陣列#Codechef Merciless Chef

#線段樹,樹狀陣列#Codechef Merciless Chef

MLCHEF


分析

首先按照dfs序將子樹轉換為區間,其實就是區間減和區間維護最小值判斷是否大於0

因為大於0一定最多隻有 \(n\) 個,所以直接將一個數記錄被刪除並設為正無窮。


程式碼

#include <cstdio>
#include <cctype>
#include <vector>
using namespace std;
const int N=100011; vector<int>K[N];
int dfn[N],nfd[N],tot,a[N],rfn[N],c[N],n,w[N<<2],p[N<<2],lazy[N<<2];
int iut(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
void print(int ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
void dfs(int x){
	int len=K[x].size();
	dfn[x]=++tot,nfd[tot]=x;
	for (int i=0;i<len;++i) dfs(K[x][i]); 
    rfn[x]=tot;
}
void pup(int k){ 
	if (w[k<<1]<w[k<<1|1]) p[k]=p[k<<1],w[k]=w[k<<1];
	    else p[k]=p[k<<1|1],w[k]=w[k<<1|1]; 
}
void build(int k,int l,int r){
	if (l==r){
		p[k]=l,w[k]=a[nfd[l]];
		return;
	}
	int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	pup(k);
}
void update(int k,int l,int r,int x,int y,int z){
	if (l==x&&r==y){
		lazy[k]+=z,w[k]+=z;
		return;
	}
	int mid=(l+r)>>1;
	if (lazy[k]){
		w[k<<1|1]+=lazy[k],lazy[k<<1|1]+=lazy[k];
		w[k<<1]+=lazy[k],lazy[k<<1]+=lazy[k],lazy[k]=0;
	}
	if (y<=mid) update(k<<1,l,mid,x,y,z);
	else if (x>mid) update(k<<1|1,mid+1,r,x,y,z);
	    else update(k<<1,l,mid,x,mid,z),update(k<<1|1,mid+1,r,mid+1,y,z);
	pup(k);
}
void upd(int k,int l,int r,int x){
	if (l==r){
		w[k]=0x3f3f3f3f,
		lazy[k]=0,p[k]=l;
		return;
	}
	int mid=(l+r)>>1;
	if (lazy[k]){
		w[k<<1|1]+=lazy[k],lazy[k<<1|1]+=lazy[k];
		w[k<<1]+=lazy[k],lazy[k<<1]+=lazy[k],lazy[k]=0;
	}
	if (x<=mid) upd(k<<1,l,mid,x);
	    else upd(k<<1|1,mid+1,r,x);
	pup(k);
}
void Update(int x){for (;x<=n;x+=-x&x) --c[x];}
int query(int x){int ans=0; for (;x;x-=-x&x) ans+=c[x]; return ans;}
int main(){
	n=iut(),tot=-1,a[0]=0x3f3f3f3f;
	for (int i=1;i<=n;++i)
		a[i]=iut(),K[iut()].push_back(i),c[i]=-i&i;
	dfs(0),build(1,1,n);
	for (int Q=iut();Q;--Q){
		int opt=iut(),x=iut();
		if (opt==1){
			int y=iut();
			if (dfn[x]<rfn[x]) update(1,1,n,dfn[x]+1,rfn[x],-y);
			while (w[1]<=0) Update(p[1]),upd(1,1,n,p[1]);
		}else print(query(rfn[x])-query(dfn[x])),putchar(10);
	}
	return 0;
}