[FJOI2018]领导集团问题
Posted pthws
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[FJOI2018]领导集团问题相关的知识,希望对你有一定的参考价值。
https://www.luogu.org/problemnew/show/P4577
带区间修改的线段树合并
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int N=200005; int n,i,j,w[N],ch[N*31][2],mx[N*31],add[N*31],cnt,root[N],head[N],adj[N],nxt[N];//数组别开小了 void pushdown(int o,int l,int r) if(add[o]) if(ch[o][0]) add[ch[o][0]]+=add[o],mx[ch[o][0]]+=add[o]; if(ch[o][1]) add[ch[o][1]]+=add[o],mx[ch[o][1]]+=add[o]; add[o]=0; void merge(int &o1,int o2,int l,int r,int x,int y) if(!o2) add[o1]+=y; mx[o1]+=y; return; if(!o1) o1=o2; add[o1]+=x; mx[o1]+=x; return; if(l==r) x=max(x,mx[o1]),y=max(y,mx[o2]); mx[o1]=max(mx[o1]+y,mx[o2]+x); return; int mid=l+r>>1; pushdown(o1,l,r); pushdown(o2,l,r); mx[0]=0; int X=max(x,mx[ch[o1][1]]),Y=max(y,mx[ch[o2][1]]); merge(ch[o1][0],ch[o2][0],l,mid,X,Y); merge(ch[o1][1],ch[o2][1],mid+1,r,x,y); mx[0]=0; mx[o1]=max(mx[ch[o1][0]],mx[ch[o1][1]]); void update(int &o,int l,int r,int x,int y) if(!o) o=++cnt; if(l==r) mx[o]=max(mx[o],y+1); return; pushdown(o,l,r); int mid=l+r>>1; if(x<=mid) update(ch[o][0],l,mid,x,y); else update(ch[o][1],mid+1,r,x,y); mx[0]=0; mx[o]=max(mx[ch[o][0]],mx[ch[o][1]]); int query(int o,int l,int r,int x,int y) if(!o) return 0; if(l>=x&&r<=y) return mx[o]; int mid=l+r>>1,rtn=0; pushdown(o,l,r); if(x<=mid) rtn=query(ch[o][0],l,mid,x,y); if(y>mid) rtn=max(rtn,query(ch[o][1],mid+1,r,x,y)); return rtn; void dfs(int x) for(int y=head[x];y;y=nxt[y]) dfs(adj[y]); if(!root[x]) root[x]=root[adj[y]]; else merge(root[x],root[adj[y]],0,1000000000,0,0); update(root[x],0,1000000000,w[x],query(root[x],0,1000000000,w[x],1000000000)); int main() freopen("leader.in","r",stdin); freopen("leader.out","w",stdout); scanf("%d",&n); for(i=1;i<=n;++i) scanf("%d",w+i); for(i=1;i<n;++i) scanf("%d",&j); adj[i]=i+1; nxt[i]=head[j]; head[j]=i; dfs(1); printf("%d",mx[root[1]]); return 0;
以上是关于[FJOI2018]领导集团问题的主要内容,如果未能解决你的问题,请参考以下文章