• 51nod1462 树据结构


    $n leq 100000$的树支持$m leq 100000$个操作:每个点有两个权值$a$和$b$,一,链加;二,链上$b_i+=a_i*d$,问最后所有的$b_i$。

    这个题我在看到之前有想过链上的情况,当时以为标记是O(1)下传的就没细想。现在看来需要一些特殊技巧。首先链剖加线段树。

    方法一:把$a$的区间加标记永久化,然后记标记:$b$的区间共同增量;$b$的区间增加次数。下传时,$a$不下传,次数直接加给儿子后清零,增量$zeng_{son}+=zeng_{fa}+abiaoji_{son}*cishu_{fa}$。最后所有标记一起推下去。

    方法二:可用一个矩阵进行一次操作:转自此

      1 //#include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 //#include<time.h>
      5 //#include<complex>
      6 //#include<set>
      7 #include<queue>
      8 //#include<vector>
      9 #include<algorithm>
     10 #include<stdlib.h>
     11 using namespace std;
     12 
     13 #define LL long long
     14 int qread()
     15 {
     16     char c; int s=0,f=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (f=-1);
     17     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*f;
     18 }
     19 
     20 //Pay attention to '-' , LL and double of qread!!!!
     21 
     22 int n,m;
     23 #define maxn 200011
     24 
     25 struct Edge{int to,next;}edge[maxn<<1]; int first[maxn],le=2;
     26 void in(int x,int y) {Edge &e=edge[le]; e.to=y; e.next=first[x]; first[x]=le++;}
     27 
     28 int fa[maxn],id[maxn],top[maxn],dep[maxn],size[maxn],hea[maxn],Time=0,list[maxn];
     29 void dfs1(int x)
     30 {
     31     size[x]=1;
     32     for (int i=first[x];i;i=edge[i].next)
     33     {
     34         Edge &e=edge[i];
     35         dep[e.to]=dep[x]+1; fa[e.to]=x;
     36         dfs1(e.to);
     37         size[x]+=size[e.to]; if (size[e.to]>size[hea[x]]) hea[x]=e.to;
     38     }
     39 }
     40 void dfs2(int x,int from)
     41 {
     42     top[x]=from; id[x]=++Time; list[Time]=x;
     43     if (hea[x]) dfs2(hea[x],from);
     44     for (int i=first[x];i;i=edge[i].next)
     45     {
     46         Edge &e=edge[i]; if (e.to==hea[x]) continue;
     47         dfs2(e.to,e.to);
     48     }
     49 }
     50 
     51 LL ans[maxn];
     52 struct SMT
     53 {
     54     struct Node
     55     {
     56         int ls,rs;
     57         LL sv,st,nt;
     58     }a[maxn<<1];
     59     int size,n;
     60     void build(int &x,int L,int R)
     61     {
     62         x=++size; if (L==R) return;
     63         int mid=(L+R)>>1;
     64         build(a[x].ls,L,mid); build(a[x].rs,mid+1,R);
     65     }
     66     void clear(int N) {n=N; size=0; int x; build(x,1,n);}
     67     void addsingle(int x,LL fst,LL fnt)
     68     {
     69         a[x].st+=fst+a[x].sv*fnt;
     70         a[x].nt+=fnt;
     71     }
     72     void down(int x)
     73     {addsingle(a[x].ls,a[x].st,a[x].nt); addsingle(a[x].rs,a[x].st,a[x].nt); a[x].st=a[x].nt=0;}
     74     int ql,qr,d; LL vv;
     75     void OP1(int x,int L,int R)
     76     {
     77         if (ql<=L && R<=qr) {a[x].sv+=d; return;}
     78         down(x);
     79         int mid=(L+R)>>1;
     80         if (ql<=mid) OP1(a[x].ls,L,mid);
     81         if (qr>mid) OP1(a[x].rs,mid+1,R);
     82     }
     83     void op1(int L,int R,int d) {ql=L; qr=R; this->d=d; OP1(1,1,n);}
     84     void OP2(int x,int L,int R)
     85     {
     86         if (ql<=L && R<=qr) {a[x].st+=(vv+a[x].sv)*d; a[x].nt+=d; return;}
     87         down(x); vv+=a[x].sv;
     88         int mid=(L+R)>>1;
     89         if (ql<=mid) OP2(a[x].ls,L,mid);
     90         if (qr>mid) OP2(a[x].rs,mid+1,R);
     91         vv-=a[x].sv;
     92     }
     93     void op2(int L,int R,int d) {ql=L; qr=R; this->d=d; vv=0; OP2(1,1,n);}
     94     
     95     void dfs(int x,int L,int R)
     96     {
     97         if (L==R)
     98         {
     99             int u=list[L];
    100             ans[u]=a[x].st;
    101             return;
    102         }
    103         down(x);
    104         int mid=(L+R)>>1;
    105         dfs(a[x].ls,L,mid); dfs(a[x].rs,mid+1,R);
    106     }
    107     void dfs() {dfs(1,1,n);}
    108 }t;
    109 
    110 void ope(int x,int y,int d,int type)
    111 {
    112     while (top[x]!=top[y])
    113     {
    114         if (dep[top[x]]<dep[top[y]]) x^=y^=x^=y;
    115         if (type==1) t.op1(id[top[x]],id[x],d);
    116         else t.op2(id[top[x]],id[x],d);
    117         x=fa[top[x]];
    118     }
    119     if (dep[x]>dep[y]) x^=y^=x^=y;
    120     if (type==1) t.op1(id[x],id[y],d);
    121     else t.op2(id[x],id[y],d);
    122 }
    123 
    124 int main()
    125 {
    126     n=qread();
    127     for (int i=2,x;i<=n;i++) {x=qread(); in(x,i);}
    128     dfs1(1); dfs2(1,1);
    129     
    130     t.clear(n);
    131     m=qread();
    132     int op,x,d;
    133     while (m--)
    134     {
    135         op=qread(); x=qread(); d=qread();
    136         ope(1,x,d,op);
    137     }
    138     t.dfs();
    139     for (int i=1;i<=n;i++) printf("%lld
    ",ans[i]);
    140     return 0;
    141 }
    View Code
  • 相关阅读:
    jmeter循环控制器
    SQL语句
    Linux防火墙常用命令
    利用cookie,实现刷新页面跳转,左侧菜单点击后状态保持不变。
    JQUERY动态生成当前年份的前5年以及后 2年
    (个人累积,分享)制作iconfont并转化图标代码使用
    如果一张要显示的图片穿插着两个路径该怎么解决?
    上传图片后台写法
    分析器错误消息:未能加载类型“XXXXXXX”
    尝试加载应用时出现了以下错误
  • 原文地址:https://www.cnblogs.com/Blue233333/p/9169168.html
Copyright © 2020-2023  润新知