[uoj418]三角形

将过程倒序,即每次放$\sum w_{son}$个石子并收回$w_{i}$个石子,并要求父亲优先于儿子操作

关于这个问题,其中一个弱化版(仅询问根节点)即hdu6326,具体做法可参考该链接

在此基础上,对每一个节点维护(仅考虑其子树内时)当前该点上的"怪兽"属性

此时,将$k$合并即将 $fa_{k}$到$fa_{k}$所在块最浅的点的链 上所有点的"怪兽"与$k$上的合并

将其差分,注意到所有$k$相对顺序不变(与合并顺序相同),进而线段树合并维护即可

时间复杂度为$o(n\log n)$,可以通过

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 200005
 4 #define M 10000000
 5 #define ll long long
 6 #define mid (l+r>>1)
 7 int n,V,a[N],fa[N],rt[N],ls[M],rs[M],vis[M];
 8 vector<int>e[N],v[N];
 9 struct Data{
10     ll a,b;
11     bool operator < (const Data &n)const{
12         if ((a<b)!=(n.a<n.b))return a<b;
13         return (a<b ? a<n.a : b>n.b);
14     }
15     Data operator + (const Data &n)const{
16         ll a0=max(a,a-b+n.a);
17         return Data{a0,b-a+n.b-n.a+a0};
18     }
19 }w[N],W[N],ans[N],f[M];set<pair<Data,int> >S;
20 int find(int k){
21     return (k==fa[k] ? k : fa[k]=find(fa[k]));
22 }
23 void update(int &k,int l,int r,int x){
24     if (!k)k=++V;
25     if (l==r){
26         vis[k]^=1,f[k]=(vis[k] ? W[l] : Data{0,0});
27         return;
28     }
29     if (x<=mid)update(ls[k],l,mid,x);
30     else update(rs[k],mid+1,r,x);
31     f[k]=f[ls[k]]+f[rs[k]];
32 }
33 int merge(int k1,int k2,int l,int r){
34     if ((!k1)||(!k2))return k1+k2;
35     if (l==r){
36         vis[k1]^=vis[k2],f[k1]=(vis[k1] ? W[l] : Data{0,0});
37         return k1;
38     }
39     ls[k1]=merge(ls[k1],ls[k2],l,mid);
40     rs[k1]=merge(rs[k1],rs[k2],mid+1,r);
41     f[k1]=f[ls[k1]]+f[rs[k1]];
42     return k1;
43 }
44 void dfs(int k){
45     for(int i:e[k])dfs(i),rt[k]=merge(rt[k],rt[i],1,n-1);
46     for(int i:v[k])update(rt[k],1,n-1,i);
47     ans[k]=ans[k]+f[rt[k]];
48 }
49 int main(){
50     scanf("%*d%d",&n);
51     for(int i=2;i<=n;i++){
52         scanf("%d",&a[i]);
53         e[a[i]].push_back(i);
54     }
55     for(int i=1;i<=n;i++){
56         scanf("%lld",&w[i].b);
57         if (i>1)w[a[i]].a+=w[i].b;
58     }
59     for(int i=1;i<=n;i++){
60         fa[i]=i,ans[i]=Data{w[i].b,0}+w[i];
61         if (i>1)S.insert(make_pair(w[i],i));
62     }
63     for(int i=1;i<n;i++){
64         int k=(*S.begin()).second;S.erase(S.begin());
65         int f=fa[k]=find(a[k]);
66         if (f>1)S.erase(make_pair(w[f],f));
67         w[f]=w[f]+w[k],W[i]=w[k];
68         v[a[k]].push_back(i),v[a[f]].push_back(i);
69         if (f>1)S.insert(make_pair(w[f],f));
70     }
71     dfs(1);
72     for(int i=1;i<=n;i++)printf("%lld ",ans[i].a);
73     return 0;
74 }
View Code

 

posted @ 2022-06-26 16:58  PYWBKTDA  阅读(32)  评论(0编辑  收藏  举报