码迷,mamicode.com
首页 > 其他好文 > 详细

[ZJOI2008]树的统计

时间:2017-04-13 20:54:14      阅读:262      评论:0      收藏:0      [点我收藏+]

标签:ios   memset   inf   tps   cstring   void   namespace   sub   记录   

洛谷传送门

第一遍树链剖分,打的很难受。

其中拉闸了,检查真是费劲。

详解什么的就不给了。(其实我现在也看不懂)

看模板的专题吧。

技术分享
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #define rt 1, 1, n
  5 #define ls o << 1, l, m
  6 #define rs o << 1 | 1, m + 1, r
  7 
  8 using namespace std;
  9 
 10 const int maxn = 300001;
 11 const int INF = 99999999;
 12 int n, m, q, cnt, tim;
 13 int a[maxn], head[maxn], to[maxn << 2], next[maxn << 2], deep[maxn], size[maxn];
 14 int  son[maxn], top[maxn], f[maxn], tid[maxn], rank[maxn], sumv[maxn], maxv[maxn];
 15 //a节点权值, deep节点深度, size以x为根的子树节点个数, son重儿子, top当前节点所在链的顶端节点
 16 //f当前节点父亲, tid保存树中每个节点剖分后的新编号,  rank保存当前节点在线段树中的位置 
 17 
 18 void add(int x, int y)
 19 {
 20     to[cnt] = y;
 21     next[cnt] = head[x];
 22     head[x] = cnt++;
 23 }
 24 
 25 void dfs1(int u, int father)//记录所有重边 
 26 {
 27     int i, v;
 28     size[u] = 1;
 29     for(i = head[u]; i != -1; i = next[i])
 30     {
 31         v = to[i];
 32         if(v == father) continue;
 33         deep[v] = deep[u] + 1;
 34         f[v] = u;
 35         dfs1(v, u);
 36         size[u] += size[v];
 37         if(son[u] == -1 || size[v] > size[son[u]]) son[u] = v;
 38     }
 39 }
 40 
 41 void dfs2(int u, int tp)
 42 {
 43     int i, v;
 44     top[u] = tp;
 45     tid[u] = ++tim;
 46     rank[tim] = u;
 47     if(son[u] == -1) return;
 48     dfs2(son[u], tp);//重边 
 49     for(i = head[u]; i != -1; i = next[i])
 50     {
 51         v = to[i];
 52         if(v != son[u] && v != f[u]) dfs2(v, v);//轻边 
 53     }
 54 }
 55 
 56 void pushup(int o)
 57 {
 58     sumv[o] = sumv[o << 1] + sumv[o << 1 | 1];
 59     maxv[o] = max(maxv[o << 1], maxv[o << 1 | 1]);
 60 }
 61 
 62 void updata(int o, int l, int r, int d, int x)
 63 {
 64     int m = (l + r) >> 1;
 65     if(l == r)
 66     {
 67         sumv[o] = maxv[o] = x;
 68         return;
 69     }
 70     if(d <= m) updata(ls, d, x);
 71     else updata(rs, d, x);
 72     pushup(o);
 73 }
 74 
 75 void build(int o, int l, int r)
 76 {
 77     int m = (l + r) >> 1;
 78     if(l == r)
 79     {
 80         sumv[o] = maxv[o] = a[rank[l]];
 81         return;
 82     }
 83     build(ls);
 84     build(rs);
 85     pushup(o);
 86 }
 87 
 88 int querymax(int o, int l, int r, int ql, int qr)
 89 {
 90     int m = (l + r) >> 1, ans = -INF;
 91     if(ql <= l && r <= qr) return maxv[o];
 92     if(ql <= m) ans = max(ans, querymax(ls, ql, qr));
 93     if(m < qr) ans = max(ans, querymax(rs, ql, qr));
 94     pushup(o);
 95     return ans;
 96 }
 97 
 98 int qmax(int u, int v)
 99 {
100     int ans = -INF;
101     while(top[u] != top[v])
102     {
103         if(deep[top[u]] < deep[top[v]]) swap(u, v);
104         ans = max(ans, querymax(rt, tid[top[u]], tid[u]));
105         u = f[top[u]];
106     }
107     if(deep[u] < deep[v]) swap(u, v);
108     ans = max(ans, querymax(rt, tid[v], tid[u]));
109     return ans;
110 }
111 
112 int querysum(int o, int l, int r, int ql, int qr)
113 {
114     int m = (l + r) >> 1, ans = 0;
115     if(ql <= l && r <= qr) return sumv[o];
116     if(ql <= m) ans += querysum(ls, ql, qr);
117     if(m < qr) ans += querysum(rs, ql, qr);
118     pushup(o);
119     return ans;
120 }
121 
122 int qsum(int u, int v)
123 {
124     int ans = 0;
125     while(top[u] != top[v])
126     {
127         if(deep[top[u]] < deep[top[v]]) swap(u, v);
128         ans += querysum(rt, tid[top[u]], tid[u]);
129         u = f[top[u]];
130     }
131     if(deep[u] < deep[v]) swap(u, v);
132     ans += querysum(rt, tid[v], tid[u]);
133     return ans;
134 }
135 
136 int main()
137 {
138     int i, j, x, y;
139     char s[11];
140     memset(head, -1, sizeof(head));
141     memset(son, -1, sizeof(son));
142     scanf("%d", &n);
143     for(i = 1; i < n; i++)
144     {
145         scanf("%d %d", &x, &y);
146         add(x, y);
147         add(y, x);
148     }
149     for(i = 1; i <= n; i++) scanf("%d", &a[i]);
150     deep[1] = 1;
151     f[1] = 1;
152     dfs1(1, -1);
153     dfs2(1, 1);
154     build(rt);
155     scanf("%d", &q);
156     for(i = 1; i <= q; i++)
157     {
158         scanf("%s %d %d", s, &x, &y);
159         if(s[1] == H) updata(rt, tid[x], y);
160         if(s[1] == M) printf("%d\n", qmax(x, y));
161         if(s[1] == S) printf("%d\n", qsum(x, y));
162     }
163     return 0;
164 }
View Code

 

[ZJOI2008]树的统计

标签:ios   memset   inf   tps   cstring   void   namespace   sub   记录   

原文地址:http://www.cnblogs.com/zhenghaotian/p/6705918.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!