山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

Tsinsen A1303. tree(伍一鸣) (LCT+处理标记)

 

【题目链接】

 

    http://www.tsinsen.com/A1303

 

【题意】

 

    给定一棵树,提供树上路径乘/加一个数,加边断边,查询路径和的操作。

 

【思路】

 

    LCT+传标

    一次dfs构造LCT。

    LCT维护信息:v,sum,rev,add,mul,siz

    提取路径(u,v):evert(u)->Access(v),splay(v),此时以v为根的splay辅助树即u->v的路径,直接进行操作即可。

    关于下传标记:

        Hezecong神犇的总结

    对于一个节点的标记,始终保持该标记已作用在该节点上。

  给节点打标记后作用于该节点,每次传标,给儿子打上标记且作用于该儿子。

    对于覆盖类标记,直接覆盖即可。反转标记单独处理。

  对于非覆盖类标记,考虑操作先后:先下传乘法标记,然后下传加法标记。对于乘法下传,还需要作用在加法标记上。

 

【代码】

 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #define FOR(a,b,c) for(int a=b;a<=c;a++)
  5 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
  6 using namespace std;
  7 
  8 typedef long long ll;
  9 typedef unsigned int ul;
 10 const int N = 4e5+10;
 11 const int MOD = 51061;
 12 
 13 namespace LCT {
 14 
 15     struct Node {
 16         Node *ch[2],*fa;
 17         ul v,siz,rev,add,mul,sum;
 18         Node() ;
 19         //给当前结点打上标记 且更新当前结点 
 20         void mulv(int x) {
 21             mul=(mul*x)%MOD;
 22             v=(v*x)%MOD;
 23             add=(add*x)%MOD;
 24             sum=(sum*x)%MOD;
 25         }
 26         void addv(int x) {
 27             v=(v+x)%MOD;
 28             add=(add+x)%MOD;
 29             sum=(sum+siz*x)%MOD;
 30         }
 31         void reverse() {
 32             rev^=1;
 33             swap(ch[0],ch[1]);
 34         }
 35         //up push down
 36         void up_push() {
 37             if(fa->ch[0]==this||fa->ch[1]==this)
 38                 fa->up_push();
 39             if(mul^1) {                             //mul != 1
 40                 ch[0]->mulv(mul);
 41                 ch[1]->mulv(mul);
 42                 mul=1;
 43             }
 44             if(add) {
 45                 ch[0]->addv(add);
 46                 ch[1]->addv(add);
 47                 add=0;
 48             }
 49             if(rev) {
 50                 ch[0]->reverse();
 51                 ch[1]->reverse();
 52                 rev=0;
 53             }
 54         }
 55         void maintain() {
 56             siz=ch[0]->siz+ch[1]->siz+1;
 57             sum=(ch[0]->sum+ch[1]->sum+v)%MOD;
 58         }
 59     } *null=new Node, T[N];
 60     Node:: Node() {
 61         fa=ch[0]=ch[1]=null;
 62         add=rev=0,mul=siz=1;
 63         sum=v=0;
 64     }
 65     
 66     void rot(Node* o,int d) {
 67         Node *p=o->fa;
 68         p->ch[d]=o->ch[d^1];
 69         o->ch[d^1]->fa=p;
 70         o->ch[d^1]=p;
 71         o->fa=p->fa;
 72         if(p==p->fa->ch[0])
 73             p->fa->ch[0]=o;
 74         else if(p==p->fa->ch[1])
 75             p->fa->ch[1]=o;
 76         p->fa=o;
 77         p->maintain();
 78     }
 79     void splay(Node* o) {
 80         o->up_push();
 81         Node *nf,*nff;
 82         while(o->fa->ch[0]==o||o->fa->ch[1]==o) {
 83             nf=o->fa,nff=nf->fa;
 84             if(o==nf->ch[0]) {
 85                 if(nf==nff->ch[0]) rot(nf,0);
 86                 rot(o,0);
 87             } else {
 88                 if(nf==nff->ch[1]) rot(nf,1);
 89                 rot(o,1);
 90             }
 91         }
 92         o->maintain();
 93     }
 94     void Access(Node* o) {
 95         Node* son=null;
 96         while(o!=null) {
 97             splay(o);
 98             o->ch[1]=son;
 99             o->maintain();
100             son=o; o=o->fa;
101         }
102     }
103     void evert(Node* o) {
104         Access(o); 
105         splay(o);
106         o->reverse();
107     }
108     void Link(Node *u,Node *v) {
109         evert(u);
110         u->fa=v;
111     }
112     void Cut(Node *u,Node *v) {
113         evert(u);
114         Access(v); splay(v);
115         u->fa=v->ch[0]=null;
116         v->maintain();
117     }
118 
119 }
120 using namespace LCT;
121 
122 struct Edge { int v,nxt;
123 }e[N<<2];
124 int en=1,front[N];
125 void adde(int u,int v) {
126     e[++en]=(Edge){v,front[u]}; front[u]=en;
127 }
128 
129 ll read()
130 {
131     char c=getchar(); 
132     ll f=1,x=0;
133     while(!isdigit(c)) {
134         if(c=='-') f=-1; 
135         c=getchar();
136     }
137     while(isdigit(c))
138         x=x*10+c-'0',
139         c=getchar();
140     return x*f;
141 }
142 
143 int n,q;
144 
145 void build(int u,int fa) {
146     T[u].sum=T[u].v=1;
147     trav(u,i) {
148         int v=e[i].v;
149         if(v!=fa) {
150             T[v].fa=&T[u];
151             build(v,u);
152         }
153     }
154 }
155 
156 int main()
157 {
158     null->siz=null->mul=0;
159     n=read(),q=read();
160     for(int i=1;i<n;i++) {
161         int u=read(),v=read();
162         adde(u,v),adde(v,u);
163     }
164     build(1,-1);
165     char op[2];
166     int u,v,x,y;
167     while(q--) {
168         scanf("%s",&op);
169         u=read(),v=read();
170         if(op[0]=='+' || op[0]=='*') {
171             x=read();
172             evert(&T[u]);
173             Access(&T[v]); splay(&T[v]);
174             if(op[0]=='+') T[v].addv(x);
175             else T[v].mulv(x);
176         } else
177         if(op[0]=='-') {
178             x=read(),y=read();
179             Cut(&T[u],&T[v]);
180             Link(&T[x],&T[y]);
181         } else {
182             evert(&T[u]);
183             Access(&T[v]); splay(&T[v]);
184             printf("%d\n",T[v].sum);
185         }
186     }
187     return 0;
188 }

 

posted on 2016-03-25 17:23  hahalidaxin  阅读(422)  评论(0编辑  收藏  举报