[51nod1462]树据结构

题面:

  给一颗以1为根的树。
  每个点有两个权值:vi, ti,一开始全部是零。
 Q次操作:
  读入o, u, d
  o = 1 对u到根上所有点的vi += d 
  o = 2 对u到根上所有点的ti += vi * d
  最后,输出每个点的ti值(n, Q <= 100000)
  有50%的数据N,Q <= 10000
  注:所有数64位整数不会爆。
 
 
一开始以为是链剖板子题,结果发现两个标记没法共存(就是说要更新某个标记的话另一个标记得传下去)
由swm大爷的教导可得T_T,可以搞个3*3的矩阵当标记...
1,t_d,0
0,1  ,0
v,t  ,1
 
UPD:
  v表示区间内共同增加的v,t表示区间内共同增加的t,t_d表示区间内共同增加的操作2的d的总和。
  具体操作的时候怎么维护标记就算一下矩乘后的结果吧
 
操作1的话就是乘上
1,0,0
0,1,0
d,0,1
 
操作2的话就是乘上
1,d,0
0,1,0
0,0,1

UPD:所以实际上只要维护三个标记就好,不用写矩乘.....复杂度O(nlog^2n * 下传标记复杂度)

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 #define ll long long
 7 #define ui unsigned int
 8 #define ull unsigned long long
 9 const int maxn=100023,mxnode=maxn<<1;
10 struct zs{int too,pre;}e[maxn];int tot,last[maxn];
11 struct mat{ll mp[3][3];}tag[mxnode],nul={1,0,0,0,1,0,0,0,1};
12 int lc[mxnode],rc[mxnode],tt;
13 int dfn[maxn],tim,fa[maxn],bel[maxn],sz[maxn];
14 int i,j,k,n,m;
15 int L,R;mat TAG;
16 ll an[maxn];
17 
18 int ra,fh;char rx;
19 inline int read(){
20     rx=getchar(),ra=0,fh=1;
21     while((rx<'0'||rx>'9')&&rx!='-')rx=getchar();
22     if(rx=='-')fh=-1,rx=getchar();
23     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh;
24 }
25 
26 mat operator *(mat a,mat b){
27     mat c;
28     int i,j,k;
29     for(i=0;i<3;i++)for(j=0;j<3;j++)for(k=c.mp[i][j]=0;k<3;k++)
30         c.mp[i][j]+=a.mp[i][k]*b.mp[k][j];
31     return c;
32 }
33 
34 inline void pushdown(int x){
35     if(!tag[x].mp[0][1]&&!tag[x].mp[2][0])return;
36     int l=lc[x],r=rc[x];
37     tag[l]=tag[l]*tag[x],tag[r]=tag[r]*tag[x],
38     tag[x]=nul;
39 }
40 void insert(int x,int a,int b){
41     if(L<=a&&R>=b){tag[x]=tag[x]*TAG;return;}
42     pushdown(x);
43     int mid=a+b>>1;
44     if(L<=mid)insert(lc[x],a,mid);
45     if(R>mid)insert(rc[x],mid+1,b);
46 }
47 void dfss(int x,int a,int b){
48     if(a==b){an[a]=tag[x].mp[2][1];return;}
49     pushdown(x);
50     int mid=a+b>>1;
51     dfss(lc[x],a,mid),dfss(rc[x],mid+1,b);
52 }
53 void build(int a,int b){
54     int x=++tt;tag[x]=nul;
55     if(a==b)return;
56     int mid=a+b>>1;
57     lc[x]=tt+1,build(a,mid),rc[x]=tt+1,build(mid+1,b);
58 }
59 
60 
61 void dfs(int x){
62     sz[x]=1;
63     for(int i=last[x];i;i=e[i].pre)
64         fa[e[i].too]=x,dfs(e[i].too),sz[x]+=sz[e[i].too];
65 }
66 void dfs2(int x,int chain){
67     int i,mx=0;
68     bel[x]=chain,dfn[x]=++tim;
69     for(i=last[x];i;i=e[i].pre)if(sz[e[i].too]>sz[mx])mx=e[i].too;
70     if(!mx)return;
71     dfs2(mx,chain);
72     for(i=last[x];i;i=e[i].pre)if(e[i].too!=mx)dfs2(e[i].too,e[i].too);
73 }
74 void run(int x){
75     while(bel[x]!=bel[1])
76         L=dfn[bel[x]],R=dfn[x],insert(1,1,n),
77         x=fa[bel[x]];
78     L=dfn[bel[1]],R=dfn[x],insert(1,1,n);
79 }
80 
81 inline void ins(int a,int b){
82     e[++tot].too=b,e[tot].pre=last[a],last[a]=tot;
83 }
84 int main(){
85     n=read();
86     for(i=2;i<=n;i++)ins(read(),i);
87     dfs(1),dfs2(1,1);
88     build(1,n);
89     int id,x,d;
90     for(m=read();m;m--){
91         id=read(),x=read(),d=read();TAG=nul;
92         if(id==1)TAG.mp[2][0]=d;else TAG.mp[0][1]=d;
93         run(x);
94     }
95     dfss(1,1,n);
96     for(i=1;i<=n;i++)printf("%lld
",an[dfn[i]]);
97 }
View Code

还是第一次见这种题。。

原文地址:https://www.cnblogs.com/czllgzmzl/p/5943479.html