cyand1317

分类

链接

RSS

RSS Link
WC 2016 酱油记
[BZOJ 2049] [Luogu P2147] [SDOI 2008] Cave 洞穴勘测

[BZOJ 2157] 旅游

cyand1317 posted @ 2016年4月02日 17:40 in 未分类 with tags BZOJ SGT HLD , 530 阅读

切完题来水一发……

拥有良心样例数据的树链剖分模版题……

窝已经要突破天际了哈哈哈写这货都能有 250+ 行哈哈哈已经开始脑补 NOI 2005 维修数列了哈哈哈哈哈哈……(←发抽 ing)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
/**************************************************************
    Problem: 2157
    User: cyand1317
    Language: C++
    Result: Accepted
    Time:632 ms
    Memory:3472 kb
****************************************************************/
  
#include <cstdio>
#include <utility>
#include <vector>
static const int MAXN = 20006;
static const int INF = 0x7fffffff;
inline int min(int a, int b) { return a < b ? a : b; }
inline int max(int a, int b) { return a > b ? a : b; }
inline void swap(int &a, int &b) { static int t; t = a; a = b; b = t; }
  
struct __sgt_node {
    int l, r, lch, rch;
    int sum, min, max;
    bool lz_rev;
} t[MAXN * 2];
  
void sgt_push(int idx)
{
    if (t[idx].lz_rev) {
        t[idx].lz_rev = false;
        t[idx].sum = -t[idx].sum;
        int x = t[idx].min;
        t[idx].min = -t[idx].max;
        t[idx].max = -x;
        if (t[idx].lch != -1) {
            t[t[idx].lch].lz_rev ^= 1;
            t[t[idx].rch].lz_rev ^= 1;
        }
    }
}
void sgt_update(int idx)
{
    if (t[idx].lch != -1) {
        sgt_push(t[idx].lch);
        sgt_push(t[idx].rch);
        t[idx].sum = t[t[idx].lch].sum + t[t[idx].rch].sum;
        t[idx].min = min(t[t[idx].lch].min, t[t[idx].rch].min);
        t[idx].max = max(t[t[idx].lch].max, t[t[idx].rch].max);
    }
}
int sgt_querysum(int l, int r, int idx = 0)
{
    sgt_push(idx);
    if (t[idx].l >= l && t[idx].r <= r) return t[idx].sum;
    int ret = 0;
    if (t[t[idx].lch].r >= l) ret += sgt_querysum(l, r, t[idx].lch);
    if (t[t[idx].rch].l <= r) ret += sgt_querysum(l, r, t[idx].rch);
    return ret;
}
int sgt_querymax(int l, int r, int idx = 0)
{
    sgt_push(idx);
    if (t[idx].l >= l && t[idx].r <= r) return t[idx].max;
    int ret = -INF;
    if (t[t[idx].lch].r >= l) ret = max(ret, sgt_querymax(l, r, t[idx].lch));
    if (t[t[idx].rch].l <= r) ret = max(ret, sgt_querymax(l, r, t[idx].rch));
    return ret;
}
int sgt_querymin(int l, int r, int idx = 0)
{
    sgt_push(idx);
    if (t[idx].l >= l && t[idx].r <= r) return t[idx].min;
    int ret = INF;
    if (t[t[idx].lch].r >= l) ret = min(ret, sgt_querymin(l, r, t[idx].lch));
    if (t[t[idx].rch].l <= r) ret = min(ret, sgt_querymin(l, r, t[idx].rch));
    return ret;
}
void sgt_pointset(int pos, int val, int idx = 0)
{
    sgt_push(idx);
    if (t[idx].l == pos && t[idx].r == pos) {
        t[idx].sum = t[idx].min = t[idx].max = val;
    } else {
        if (pos <= t[t[idx].lch].r) sgt_pointset(pos, val, t[idx].lch);
        else sgt_pointset(pos, val, t[idx].rch);
        sgt_update(idx);
    }
}
void sgt_intvrev(int l, int r, int idx = 0)
{
    sgt_push(idx);
    if (t[idx].l >= l && t[idx].r <= r) {
        t[idx].lz_rev ^= 1;
    } else {
        if (t[t[idx].lch].r >= l) sgt_intvrev(l, r, t[idx].lch);
        if (t[t[idx].rch].l <= r) sgt_intvrev(l, r, t[idx].rch);
    }
    sgt_update(idx);
}
  
int sgt_seq[MAXN];
int sgt_build(int l, int r)
{
    static int epoch = -1;
    int idx = ++epoch;
    t[idx].l = l; t[idx].r = r;
    t[idx].lz_rev = false;
    if (l == r) {
        t[idx].lch = t[idx].rch = -1;
        t[idx].sum = t[idx].min = t[idx].max = sgt_seq[l];
    } else {
        int m = (l + r) >> 1;
        t[idx].lch = sgt_build(l, m);
        t[idx].rch = sgt_build(m + 1, r);
        sgt_update(idx);
    }
    return idx;
}
  
typedef std::pair<int, int> edge;
#define dest first
#define len  second
typedef std::vector<edge> edgelist;
  
int n;
edgelist e[MAXN];
std::pair<int, int> e_list[MAXN];
  
int par[MAXN], dep[MAXN], sts[MAXN], pfc[MAXN];
int tvn[MAXN], hct[MAXN];
int par_dist[MAXN];
  
void hld_dfs1(int r = 0, int p = -1, int d = 0)
{
    par[r] = p; dep[r] = d;
    sts[r] = 1; pfc[r] = -1;
    int max_sts = -1;
    for (edgelist::iterator i = e[r].begin(); i != e[r].end(); ++i) if (i->dest != p) {
        par_dist[i->dest] = i->len;
        hld_dfs1(i->dest, r, d + 1);
        sts[r] += sts[i->dest];
        if (max_sts < sts[i->dest]) {
            max_sts = sts[i->dest];
            pfc[r] = i->dest;
        }
    }
}
void hld_dfs2(int r = 0, int t = 0)
{
    static int epoch = -1;
    tvn[r] = ++epoch;
    sgt_seq[epoch] = par_dist[r];
    hct[r] = t;
    if (pfc[r] != -1) hld_dfs2(pfc[r], t);
    for (edgelist::iterator i = e[r].begin(); i != e[r].end(); ++i)
        if (i->dest != par[r] && i->dest != pfc[r]) hld_dfs2(i->dest, i->dest);
}
inline void hld_jumpsum(int &u, int &ans)
{
    int v = hct[u];
    ans += sgt_querysum(tvn[v], tvn[u]);
    u = par[v];
}
int hld_querysum(int u, int v)
{
    if (dep[u] > dep[v]) swap(u, v);
    int ans = 0;
    while (hct[u] != hct[v]) {
        if (dep[hct[u]] < dep[hct[v]]) hld_jumpsum(v, ans);
        else hld_jumpsum(u, ans);
    }
    if (dep[u] > dep[v]) swap(u, v);
    if (u != v) ans += sgt_querysum(tvn[u] + 1, tvn[v]);
    return ans;
}
inline void hld_jumpmin(int &u, int &ans)
{
    int v = hct[u];
    ans = min(ans, sgt_querymin(tvn[v], tvn[u]));
    u = par[v];
}
int hld_querymin(int u, int v)
{
    if (dep[u] > dep[v]) swap(u, v);
    int ans = INF;
    while (hct[u] != hct[v]) {
        if (dep[hct[u]] < dep[hct[v]]) hld_jumpmin(v, ans);
        else hld_jumpmin(u, ans);
    }
    if (dep[u] > dep[v]) swap(u, v);
    if (u != v) ans = min(ans, sgt_querymin(tvn[u] + 1, tvn[v]));
    return ans;
}
inline void hld_jumpmax(int &u, int &ans)
{
    int v = hct[u];
    ans = max(ans, sgt_querymax(tvn[v], tvn[u]));
    u = par[v];
}
int hld_querymax(int u, int v)
{
    if (dep[u] > dep[v]) swap(u, v);
    int ans = -INF;
    while (hct[u] != hct[v]) {
        if (dep[hct[u]] < dep[hct[v]]) hld_jumpmax(v, ans);
        else hld_jumpmax(u, ans);
    }
    if (dep[u] > dep[v]) swap(u, v);
    if (u != v) ans = max(ans, sgt_querymax(tvn[u] + 1, tvn[v]));
    return ans;
}
inline void hld_jumprev(int &u)
{
    int v = hct[u];
    sgt_intvrev(tvn[v], tvn[u]);
    u = par[v];
}
void hld_pathrev(int u, int v)
{
    if (dep[u] > dep[v]) swap(u, v);
    while (hct[u] != hct[v]) {
        if (dep[hct[u]] < dep[hct[v]]) hld_jumprev(v);
        else hld_jumprev(u);
    }
    if (dep[u] > dep[v]) swap(u, v);
    if (u != v) sgt_intvrev(tvn[u] + 1, tvn[v]);
}
inline void hld_pointset(int u, int v, int val)
{
    if (par[u] == v) sgt_pointset(tvn[u], val);
    else sgt_pointset(tvn[v], val);
}
  
int main()
{
    scanf("%d", &n);
    int u, v, w;
    for (int i = 1; i < n; ++i) {
        scanf("%d%d%d", &u, &v, &w);
        e[u].push_back(edge(v, w));
        e[v].push_back(edge(u, w));
        e_list[i] = std::make_pair(u, v);
    }
    hld_dfs1();
    hld_dfs2();
    sgt_build(0, n - 1);
  
    int m;
    scanf("%d", &m);
    char op[16];
    int a1, a2;
    do {
        scanf("%s%d%d", op, &a1, &a2);
        if (/*!strcmp(op, "C")*/ op[0] == 'C') hld_pointset(e_list[a1].first, e_list[a1].second, a2);
        else if (/*!strcmp(op, "N")*/ op[0] == 'N') hld_pathrev(a1, a2);
        else if (/*!strcmp(op, "SUM")*/ op[0] == 'S') printf("%d\n", hld_querysum(a1, a2));
        else if (/*!strcmp(op, "MIN")*/ op[1] == 'I') printf("%d\n", hld_querymin(a1, a2));
        else /*if (!strcmp(op, "MAX"))*/ printf("%d\n", hld_querymax(a1, a2));
    } while (--m);
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter