shjwudp

导航

 

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036

解:树链剖分基础题

对于线性表,我们可以通过线段树、树状数组等数据结构成段修改成段查询,如果想要在树上成段修改查询,我们就需要进行树剖

树剖的大体思路是把树拆成链然后以一定次序放在线性表上,然后利用各种数据结构处理线性表

比如处理树上两点u、v之间的路径,我们要知道这条路径与之前拆分的哪些链相交,然后查询线性表上相交部分

那么时间复杂度为=路径与拆分链相交数*数据结构处理每条链时间

可以有各种拆分链方法,目前最好的一种是轻重链拆分,拆分后保证任意路径穿过拆分链数为log(n)

树剖学习推荐博客:http://blog.sina.com.cn/s/blog_6974c8b20100zc61.html

习题推荐:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28982#overview

  1 /*
  2  * Problem:  
  3  * Author:  SHJWUDP
  4  * Created Time:  2015/6/10 星期三 23:13:56
  5  * File Name: 233.cpp
  6  * State: 
  7  * Memo: 
  8  */
  9 #include <iostream>
 10 #include <cstdio>
 11 #include <cstring>
 12 #include <algorithm>
 13 
 14 using namespace std;
 15 
 16 const int MaxA=3e4+7;
 17 
 18 struct Edge {
 19     int v, nt;
 20     Edge(){}
 21     Edge(int v, int nt):v(v), nt(nt){}
 22 } edges[MaxA<<1];
 23 
 24 int head[MaxA], edgeNum;
 25 
 26 struct SegmentTree {
 27     int n;
 28     int c[MaxA<<2][2]; ///0:sum 1:max
 29     int *val;
 30     int p, v;
 31     int L, R, op;
 32 #define lson l, m, rt<<1
 33 #define rson m+1, r, rt<<1|1
 34     
 35     void pushUp(int rt) {
 36         c[rt][0]=c[rt<<1][0]+c[rt<<1|1][0];
 37         c[rt][1]=max(c[rt<<1][1], c[rt<<1|1][1]);
 38     }
 39 
 40     void doBuild(int l, int r, int rt) {
 41         if(l==r) {
 42             c[rt][0]=c[rt][1]=val[l];
 43         } else {
 44             int m=(l+r)>>1;
 45             doBuild(lson);
 46             doBuild(rson);
 47             pushUp(rt);
 48         }
 49     }
 50 
 51     void build(int n, int* val) {
 52         this->n=n; this->val=val;
 53         doBuild(1, n, 1);
 54     }
 55 
 56     void doUpdate(int l, int r, int rt) {
 57         if(l==r) {
 58             c[rt][0]=c[rt][1]=v;
 59         } else {
 60             int m=(l+r)>>1;
 61             if(p<=m) doUpdate(lson);
 62             else doUpdate(rson);
 63             pushUp(rt);
 64         }
 65     }
 66 
 67     void update(int p, int v) {
 68         this->p=p; this->v=v;
 69         doUpdate(1, n, 1);
 70     }
 71 
 72     int doQuery(int l, int r, int rt) {
 73         if(L<=l && r<=R) {
 74             return c[rt][op];
 75         } else {
 76             int m=(l+r)>>1;
 77             int res=(op==0?0:0x80000000); 
 78             if(L<=m) res=(op==0?res+doQuery(lson):max(res, doQuery(lson)));
 79             if(m<R) res=(op==0?res+doQuery(rson):max(res, doQuery(rson)));
 80             return res;
 81         }
 82     }
 83 
 84     int query(int L, int R, int op) {
 85         this->L=L; this->R=R; this->op=op;
 86         return doQuery(1, n, 1);
 87     }
 88 #undef lson
 89 #undef rson
 90 } st;
 91 
 92 int N;
 93 int oval[MaxA], val[MaxA];    ///oval:树结点编号对应的值
 94                             ///val:线性表编号对应的值
 95 void init() {
 96     edgeNum=0;
 97     memset(head, -1, sizeof(head));
 98 }
 99 void addEdge(int u, int v) {
100     edges[edgeNum]=Edge(v, head[u]);
101     head[u]=edgeNum++;
102 }
103 namespace LCT {
104     int fa[MaxA];        ///fa[x]:x的父亲结点
105     int siz[MaxA];        ///siz[x]:x子树的结点数
106     int son[MaxA];        ///son[x]:x的重儿子,即siz最大的儿子(有平行的无所谓,随便一个即可
107     int dep[MaxA];        ///dep[x]:x的结点深度
108     int top[MaxA];        ///top[x]:x所在重链中dep值最小的结点
109                         ///重边:结点与重儿子的连边
110                         ///重链:由重边连成的路径
111     int w[MaxA];        ///w[x]:x在线性表中的编号
112     int id;                ///id:生成w数组时用的计数变量
113 
114     int dfs1(int u, int d) {
115         siz[u]=1; dep[u]=d; son[u]=-1;
116         for(int i=head[u]; ~i; i=edges[i].nt) {
117             Edge& e=edges[i];
118             if(e.v==fa[u]) continue;
119             fa[e.v]=u;
120             siz[u]+=dfs1(e.v, d+1);
121             if(son[u]==-1 || siz[son[u]]<siz[e.v]) son[u]=e.v;
122         }
123         return siz[u];
124     }
125 
126     void dfs2(int u, int tp) {    
127         w[u]=++id; top[u]=tp;
128         if(son[u]!=-1) dfs2(son[u], tp);
129         for(int i=head[u]; ~i; i=edges[i].nt) {
130             Edge& e=edges[i];
131             if(e.v==fa[u] || e.v==son[u]) continue;
132             dfs2(e.v, e.v);
133         }
134     }
135 
136     int query(int u, int v, int op) {
137         int res=(op==0?0:0x80000000);
138         int f1=top[u], f2=top[v];
139         while(f1!=f2) {
140             if(dep[f1]<dep[f2]) { swap(f1, f2); swap(u, v); }
141             res=(op==0?res+st.query(w[f1], w[u], op):max(res, st.query(w[f1], w[u], op)));
142             u=fa[f1]; f1=top[u];
143         }
144         if(dep[u]>dep[v]) swap(u, v);
145         res=(op==0?res+st.query(w[u], w[v], op):max(res, st.query(w[u], w[v], op)));
146         return res;
147     }
148 
149     void update(int p, int v) {
150         st.update(w[p], v);
151     }
152     
153     void init() {
154         int root=1;    ///随便指定树根
155         id=0;
156         fa[root]=-1;
157         dfs1(root, 0);
158         dfs2(root, root);
159         for(int i=1; i<=N; i++) {
160             val[w[i]]=oval[i];
161         }
162         st.build(N, val);
163     }
164 }
165 int main() {
166 #ifndef ONLINE_JUDGE
167     freopen("in", "r", stdin);
168     //freopen("out", "w", stdout);
169 #endif
170     while(~scanf("%d", &N)) {
171         init();
172         for(int i=1; i<N; i++) {
173             int a, b;
174             scanf("%d%d", &a, &b);
175             addEdge(a, b);
176             addEdge(b, a);
177         }
178         for(int i=1; i<=N; i++) {
179             scanf("%d", &oval[i]);
180         }
181         LCT::init();
182         int Q;
183         scanf("%d", &Q);
184         while(Q--) {
185             char op[7];
186             int a, b;
187             scanf("%s%d%d", op, &a, &b);
188             if(op[0]=='C') {
189                 LCT::update(a, b);
190             } else {
191                 if(op[1]=='S') {
192                     printf("%d\n", LCT::query(a, b, 0));
193                 } else printf("%d\n", LCT::query(a, b, 1));
194             }
195         }
196     }
197     return 0;
198 }
View Code

 

posted on 2015-06-11 00:47  shjwudp  阅读(216)  评论(0编辑  收藏  举报