• [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
  • 相关阅读:
    Django中多表的增删改查操作及聚合查询、F、Q查询
    路由控制
    路由、视图、模板主要知识点回顾
    创建文件linux
    关于shell,环境变量放置在?
    snprintf和string操作函数
    C/C++的存储区域的划分
    001
    SAMBA服务器
    归并排序原理详解!
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/16413843.html
Copyright © 2020-2023  润新知