#線段樹,樹狀陣列#Codechef Merciless Chef
阿新 • • 發佈:2022-03-14
分析
首先按照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; }