您的位置:首页 > 运维架构

POJ 3237 树链剖分+线段树维护

2018-02-28 17:21 218 查看
和QTREE1类似,增加了NEGATE操作。

记几个踩到的坑:

1. 维护数据量为n(假设n为2的幂)的线段树的大小为2*n-1,此题线段树的数组大小应为2^15-1,在写的时候写成1<<15-1,C++的<<的优先级小于-,实际开出来是2^14。

2. 这样写之后没有数组越界的异常,而是不断的WA。全局变量的内存分配在堆区,虽然访问的范围超过了数组的大小,但是在此数组之后还有其他数组的分配空间,导致线段树的更新和修改访问了其他用途的数组,导致了不断的WA。

3. 关于C++数组越界:假设有一个数组int a[5],访问a[10],a[100],a[1000]都可能不会产生越界的异常,越界异常的产生可能是访问的地址超过了操作系统给程序分配的段的范围(?),也就是说要足够大的数组下标才能触发异常。

4. 线段树的lazy tag:之前用lazy tag表示当前结点k未更新,另一种含义是当前结点的两个孩子未更新,按第二种含义来定义此题的取反标记会好写不少。

5. 在没有写线段树时交了一个树剖+暴力查询和更新的版本,结果跟用线段树维护的版本时间相差不多。。。

#include <iostream>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>
using namespace std;
const int MAX_N = 10000 + 10;
const int ST_SIZE = 1 << 15;
const int INF = ~0U >> 1;
// memset INF should be careful

int dat[MAX_N], mi[ST_SIZE], mx[ST_SIZE], neg[ST_SIZE];

struct SegTree {
// update the node k itself
// the lazy tag means k's two children hasn't been updated
void neg_it(int k) {
swap(mi[k], mx[k]);
mi[k] = -mi[k];
mx[k] = -mx[k];
neg[k] ^= 1;
}
void push_up(int k, int lc, int rc) {
mi[k] = min(mi[lc], mi[rc]);
mx[k] = max(mx[lc], mx[rc]);
}
// update k's two children lc and rc, push the lazy tag down
// k must have two children, lc and rc won't be illegal
void push_down(int k, int lc, int rc) {
if (neg[k]) {
neg_it(lc);
neg_it(rc);
neg[k] = 0;
}
}
void init(int k, int l, int r) {
if (l == r - 1) {
mi[k] = dat[l];
mx[k] = dat[l];
neg[k] = 0;
return;
}
int m = (l + r) / 2, lc = 2 * k + 1, rc = 2 * k + 2;
init(lc, l, m);
init(rc, m, r);
push_up(k, lc, rc);
neg[k] = 0; // forget to set neg here
}
void change(int k, int l, int r, int a, int c) {
if (a < l || r <= a) return;
if (l == r - 1) {
mi[k] = c;
mx[k] = c;
return;
}
int m = (l + r) / 2, lc = 2 * k + 1, rc = 2 * k + 2;
push_down(k, lc, rc);
change(lc, l, m, a, c);
change(rc, m, r, a, c);
push_up(k, lc, rc);
}
void negate(int k, int l, int r, int a, int b) {
if (b <= l || r <= a) return;
if (a <= l && r <= b) {
neg_it(k);
return;
}
int m = (l + r) / 2, lc = 2 * k + 1, rc = 2 * k + 2;
push_down(k, lc, rc);
negate(lc, l, m, a, b);
negate(rc, m, r, a, b);
push_up(k, lc, rc);
}
int query(int k, int l, int r, int a, int b) {
if (b <= l || r <= a) return -INF;
if (a <= l && r <= b) return mx[k];
int m = (l + r) / 2, lc = 2 * k + 1, rc = 2 * k + 2;
push_down(k, lc, rc);
return max(query(lc, l, m, a, b), query(rc, m, r, a, b));
}
} rmq;

struct Edge {
int to, cost;
Edge* next;
} epool[MAX_N * 2], *C, *head[MAX_N];
int es[MAX_N][3];
void add_edge(int from, int to, int cost) {
C->to = to;
C->cost = cost;
C->next = head[from];
head[from] = C++;
}

// heavy light decomposition
int N;
int parent[MAX_N], depth[MAX_N], size[MAX_N], h[MAX_N];
int top[MAX_N], pos[MAX_N], tot;
void init() {
C = epool;
memset(head, 0, sizeof(head));
memset(h, 0, sizeof(h));
tot = 0;
}

void dfs(int v, int p) {
parent[v] = p;
size[v] = 1;
for (Edge* e = head[v]; e; e = e->next) {
int u = e->to;
if (u != p) {
depth[u] = depth[v] + 1;
dfs(u, v);
size[v] += size[u];
if (h[v] == 0 || size[u] > size[h[v]]) h[v] = u;
}
}
}

void dfs2(int v, int tp) {
top[v] = tp;
pos[v] = tot++;
if (h[v]) dfs2(h[v], tp);
for (Edge* e = head[v]; e; e = e->next) {
int u = e->to;
if (u != parent[v] && u != h[v]) {
dfs2(u, u);
}
}
}

void change(int i, int c) {
rmq.change(0, 1, N, pos[es[i][0]], c);
}

void build() {
int root = (N + 1) / 2;
depth[root] = 0;
dfs(root, -1);
dfs2(root, root);
// rmq.init(0, 1, N);
for (int i = 1; i < N; i++) {
int &u = es[i][0], &v = es[i][1];
if (depth[u] < depth[v]) swap(u, v);
dat[pos[u]] = es[i][2];
// change(i, es[i][2]);
}
rmq.init(0, 1, N);
}

void neg_path(int u, int v) {
int tu = top[u], tv = top[v];
while (tu != tv) {
if (depth[tu] < depth[tv]) {
swap(tu, tv);
swap(u, v);
}
rmq.negate(0, 1, N, pos[tu], pos[u] + 1);
u = parent[tu], tu = top[u];
}
if (u != v) {
if (depth[u] < depth[v]) swap(u, v);
rmq.negate(0, 1, N, pos[h[v]], pos[u] + 1);
}
}

int query(int u, int v) {
int res = -INF;
int tu = top[u], tv = top[v];
while (tu != tv) {
if (depth[tu] < depth[tv]) {
swap(tu, tv);
swap(u, v);
}
res = max(res, rmq.query(0, 1, N, pos[tu], pos[u] + 1));
u = parent[tu], tu = top[u];
}
if (u != v) {
if (depth[u] < depth[v]) swap(u, v);
res = max(res, rmq.query(0, 1, N, pos[h[v]], pos[u] + 1));
}
return res;
}

int main() {
int t;
scanf("%d", &t);
while (t--) {
init();
scanf("%d", &N);
int a, b, c;
for (int i = 1; i < N; i++) {
scanf("%d %d %d", &a, &b, &c);
add_edge(a, b, c);
add_edge(b, a, c);
es[i][0] = a, es[i][1] = b, es[i][2] = c;
}
build();
char cmd[10];
while (scanf("%s", cmd) != EOF && cmd[0] != 'D') {
scanf("%d %d", &a, &b);
if (cmd[0] == 'Q') {
printf("%d\n", query(a, b));
} else if (cmd[0] == 'N') {
neg_path(a, b);
} else {
change(a, b);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: