和三角形沒有關係c++
只要知道兒子放置的順序,就能夠直接模擬了git
記錄歷史最大值ide
用一個pair(a,b):以後加上a個,期間最大值爲增長b個spa
合併?code
A1+A2=(a1+a2,max(b1,a1+b2))blog
放置順序考慮貪心get
比較:it
A放在B前面(和父親進行合併)當且僅當(C=A+B).b<(D=B+A).bio
分A.a和B.a的正負進行討論
初始的pair:(w[x]-∑w[son[x]],w[x])把兒子會都扔掉
初始的pair放進堆裏,取n-1次,和父親合併,加入新的連通塊的pair
鏈表維護操做序列
處理出操做順序,模擬或者線段樹合併
懶惰刪除堆自帶的bug
必需要使得決策堆和刪除堆的元素的相對順序是同樣的!
小於號重載充分!不能出現決策堆A,B,刪除堆B,A的狀況!
小於號重載充分的話:
使得除非兩者徹底相等,不然必須有固定的大小順序(未定義的話會有不少相等,比較就是隨機的)
這樣才能使得兩個堆的相對位置相同。
#include<bits/stdc++.h> #define reg register int #define il inline #define fi first #define se second #define mk(a,b) make_pair(a,b) #define numb (ch^'0') #define mid ((l+r)>>1) using namespace std; typedef long long ll; template<class T>il void rd(T &x){ char ch;x=0;bool fl=false; while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb); (fl==true)&&(x=-x); } template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');} template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');} template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');} namespace Miracle{ const int N=2e5+5; int n; struct po{ ll a,b; int id; po(){} po(ll aa,ll bb,ll dd){ a=aa;b=bb;id=dd; } po friend operator +(po a,po b){ return po(a.a+b.a,max(a.b,a.a+b.b),b.id);//warning!!! b.id } bool friend operator <(po a,po b){ // if(a.a==b.a&&a.b==b.b) return a.id<b.id; if(a.a<=0&&b.a>0) return 1; if(a.a>0&&b.a<=0) return 0; if(a.a<=0&&b.a<=0){ if(a.b!=b.b) return a.b<b.b; if(a.id!=b.id) a.id>b.id; return a.a<b.a; } if(a.a-a.b!=b.a-b.b) return a.a-a.b<b.a-b.b; if(a.id!=b.id) return a.id>b.id; return a.a>b.a; } bool friend operator ==(po a,po b){ return (a.a==b.a)&&(a.b==b.b)&&(a.id==b.id); } void op(){ cout<<a<<" "<<b<<" : "<<id<<endl; } }nc[N],ori[N]; priority_queue<po>q,d; int ff[N]; int fin(int x){ return ff[x]==x?x:ff[x]=fin(ff[x]); } int st[N],nd[N]; struct lc{ int pre,nxt,id; }p[N]; int pos[N]; struct node{ int ls,rs; po ans; }t[40*N]; int tot; int rt[N]; int vis[N]; void pushup(int x){ t[x].ans=t[t[x].ls].ans+t[t[x].rs].ans; } void upda(int &x,int l,int r,int p,po c){ x=++tot; if(l==r){t[x].ans=c;return;} if(p<=mid) upda(t[x].ls,l,mid,p,c); else upda(t[x].rs,mid+1,r,p,c); pushup(x); } int merge(int x,int y){ if(!x||!y) return x+y; t[x].ls=merge(t[x].ls,t[y].ls); t[x].rs=merge(t[x].rs,t[y].rs); pushup(x); return x; } int pa[N],w[N]; ll ans[N]; int main(){ int haha;rd(haha); rd(n); for(reg i=2;i<=n;++i) rd(pa[i]); for(reg i=1;i<=n;++i) { rd(w[i]);ff[i]=i; nc[i].id=i; nc[i].a+=w[i];nc[i].b=w[i]; nc[pa[i]].a-=w[i]; p[i].pre=p[i].nxt=0; p[i].id=i; st[i]=nd[i]=i; } for(reg i=1;i<=n;++i) { ori[i]=nc[i]; if(i!=1)q.push(nc[i]); } int o=n-1; while(o--){ po now=q.top();q.pop(); // cout<<now.a<<" "<<now.b<<" "<<now.id<<endl; if(now.id==1){ cout<<" shit ";return 0; } if(vis[now.id]){ cout<<" mmp "<<now.id<<" eqaul "<<(now==ori[now.id]);return 0; } vis[now.id]=1; int to=fin(pa[now.id]); // cout<<" to "<<to<<endl; ff[now.id]=to; if(to!=1){ d.push(nc[to]); // cout<<" dele "<<endl; // nc[to].op(); nc[to]=now+nc[to]; // nc[to].op(); // cout<<" over "<<endl; q.push(nc[to]); } p[nd[now.id]].nxt=st[to]; p[st[to]].pre=nd[now.id]; st[to]=st[now.id]; while(q.size()&&d.size()) { // po lp1=d.top(),lp2=q.top(); // cout<<" rubish "<<endl; // lp2.op();lp1.op(); if(!(q.top()==d.top())) break; q.pop(),d.pop(); } } for(reg i=2;i<=n;++i){ if(!vis[i]){ cout<<" WTF "<<i;return 0; } } int x=st[1]; for(reg i=1;i<=n;++i){ pos[x]=i; x=p[x].nxt; } // prt(pos,1,n); for(reg i=1;i<=n;++i){ upda(rt[i],1,n,pos[i],ori[i]); } // prt(rt,1,n); x=st[1]; for(reg i=1;i<=n;++i){ ans[x]=t[rt[x]].ans.b; if(pa[x]){ rt[pa[x]]=merge(rt[pa[x]],rt[x]); } x=p[x].nxt; } prt(ans,1,n); return 0; } } signed main(){ Miracle::main(); return 0; } /* Author: *Miracle* Date: 2019/4/13 19:58:12 */