bzoj3531: [Sdoi2014]旅行 (树链剖分 && 动态开点线段树)

感觉动态开点线段树空间复杂度好优秀呀

树剖裸题

把每个宗教都开一颗线段树就可以了

但是我一直TLE

然后调了一个小时

为什么呢

因为我 #define max(x, y) (x > y ? x : y)

看起来好像可以减少常数的样子

我也是这么想的(作死

事实上

ans = max(ans, query(x, y))

类似这种语句中

query(x, y)会计算两次

然后就GG了

这告诉我们还是好好用库里的函数吧

  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <vector> 
  4 using namespace std;
  5 const int N = 100000 + 10;
  6 const int M = 2000000 + 10;
  7 #define isdigit(x) (x >= '0' && x <= '9')
  8   
  9 inline void read(int &ans) {
 10     ans = 0;
 11     static char buf = getchar();
 12     register int res = 1;
 13     for (; !isdigit(buf); buf = getchar())
 14         if (buf == '-') res = -1;
 15     for (; isdigit(buf); buf = getchar())
 16         ans = ans * 10 + buf - '0';
 17     ans *= res;
 18 }
 19   
 20 int tot, n, q;
 21 int sz[N], hs[N], pos[N], fa[N], top[N], w[N], c[N], dep[N];
 22 vector < int > E[N];
 23   
 24 void dfs1(int x, int d, int f) {
 25     dep[x] = d; fa[x] = f;
 26     hs[x] = -1; sz[x] = 1;
 27     int tmp = 0;
 28     for (int i = 0; i < E[x].size(); i++) {
 29         int u = E[x][i];
 30         if (u == f) continue;
 31         dfs1(u, d + 1, x);
 32         sz[x] += sz[u];
 33         if (tmp < sz[u])
 34             tmp = sz[u], hs[x] = u;
 35     }
 36 }
 37   
 38 void dfs2(int x, int t) {
 39     top[x] = t; pos[x] = ++tot;
 40     if (hs[x] == -1)    return;
 41     dfs2(hs[x], t);
 42     for (int i = 0; i < E[x].size(); i++)
 43         if (E[x][i] != fa[x] && E[x][i] != hs[x])
 44             dfs2(E[x][i], E[x][i]);
 45 }
 46   
 47 int cnt;
 48 int sum[M], maxn[M], ls[M], rs[M], root[N];
 49   
 50 inline void pushUp(int o) {
 51     maxn[o] = max(maxn[ls[o]], maxn[rs[o]]);
 52     sum[o] = sum[ls[o]] + sum[rs[o]];
 53 }
 54   
 55 void modify(int &o, int l, int r, int p, int c) {
 56     if (!o) o = ++cnt;
 57     if (l == r) {
 58         sum[o] = maxn[o] = c;
 59         return ;
 60     }
 61     int mid = l + r >> 1;
 62     if (p <= mid)    modify(ls[o], l, mid, p, c);
 63     else    modify(rs[o], mid + 1, r, p, c);
 64     pushUp(o);
 65 }
 66   
 67 int querySum(int o, int l, int r, int L, int R) {
 68     if (!o) return 0;
 69     if (l >= L && r <= R) return sum[o];
 70     int mid = l + r >> 1, ans = 0;
 71     if (L <= mid)    ans += querySum(ls[o], l, mid, L, R);
 72     if (R > mid) ans += querySum(rs[o], mid + 1, r, L, R);
 73     return ans;
 74 }
 75   
 76 inline int querySum(int c, int x, int y) {
 77     int f1 = top[x], f2 = top[y];
 78     int ans = 0;
 79     while (f1 != f2) {
 80         if (dep[f1] < dep[f2])
 81             swap(x, y), swap(f1, f2);
 82         ans += querySum(root[c], 1, n, pos[f1], pos[x]);
 83         x = fa[f1]; f1 = top[x];
 84     }
 85     if (dep[x] > dep[y]) swap(x, y);
 86     ans += querySum(root[c], 1, n, pos[x], pos[y]);
 87     return ans;
 88 }
 89   
 90 int queryMax(int o, int l, int r, int L, int R) {
 91     if (!o) return 0;
 92     if (l >= L && r <= R) return maxn[o];
 93     int mid = l + r >> 1, ans = 0;
 94     if (L <= mid)    ans = max(ans, queryMax(ls[o], l, mid, L, R));
 95     if (R > mid) ans = max(ans, queryMax(rs[o], mid + 1, r, L, R));
 96     return ans;
 97 }
 98   
 99 inline int queryMax(int c, int x, int y) {
100     int f1 = top[x], f2 = top[y];
101     int ans = 0;
102     while (f1 != f2) {
103         if (dep[f1] < dep[f2])   
104             swap(x, y), swap(f1, f2);
105         ans = max(ans, queryMax(root[c], 1, n, pos[f1], pos[x]));
106         x = fa[f1]; f1 = top[x];
107     }
108     if (dep[x] > dep[y]) swap(x, y);
109     ans = max(ans, queryMax(root[c], 1, n, pos[x], pos[y]));
110     return ans;
111 }
112   
113   
114 int main() {
115     read(n); read(q);
116     for (int i = 1; i <= n; i++)
117         read(w[i]), read(c[i]);
118     for (int i = 1; i < n; i++) {
119         int u, v;
120         read(u); read(v);
121         E[u].push_back(v);
122         E[v].push_back(u);
123     }
124     dfs1(1, 0, 0); dfs2(1, 1);
125     for (int i = 1; i <= n; i++)
126         modify(root[c[i]], 1, n, pos[i], w[i]);
127     for (int i = 1; i <= q; i++) {
128         char ch[5]; scanf("%s", ch);
129         int x, y; read(x); read(y);
130         if (ch[0] == 'C') {
131             if (ch[1] == 'C') {
132                 modify(root[c[x]], 1, n, pos[x], 0);
133                 c[x] = y;
134                 modify(root[y], 1, n, pos[x], w[x]);
135             }
136             else {
137                 modify(root[c[x]], 1, n, pos[x], y);
138                 w[x] = y;
139             }
140         }
141         else {
142             if (ch[1] == 'S')
143                 printf("%d\n", querySum(c[x], x, y));
144             else    printf("%d\n", queryMax(c[x], x, y));
145         }
146     }
147     return 0;
148 }

 

posted @ 2018-03-19 02:29  cminus  阅读(143)  评论(0编辑  收藏  举报