您的位置:首页 > 其它

POJ 3237 Tree 树链剖分

2017-06-22 13:01 465 查看
树链剖分基础题

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 10010;
struct edge
{
int v, next;
}e[maxn*2];
int first[maxn], cnt;

int top[maxn], dep[maxn], sz[maxn], f[maxn], son[maxn], rank[maxn], tid[maxn];
int tp, tim;
int d[maxn][3];
int n;
void AddEdge(int u, int v)
{
e[cnt].v = v;
e[cnt].next = first[u];
first[u] = cnt++;

e[cnt].v = u;
e[cnt].next = first[v];
first[v] = cnt++;

}
void init()
{
memset(first, -1, sizeof(first));
cnt = 1;
memset(son, -1, sizeof(son));
tim = 0;
}

void dfs1(int u, int fa, int d)
{
sz[u] = 1;
dep[u] = d;
f[u] = fa;
for(int i = first[u]; i != -1; i = e[i].next)
{
int v = e[i].v;
if(v == fa)
continue;
dfs1(v, u, d+1);
sz[u] += sz[v];
if(son[u] == -1 || sz[son[u]] < sz[v])
son[u] = v;
}
}

void dfs2(int u, int tp)
{
top[u] = tp;
tid[u] = ++tim;
rank[tid[u]] = u;
if(son[u] == -1)
return;
dfs2(son[u], tp);
for(int i = first[u]; i != -1; i = e[i].next)
{
int v = e[i].v;
if(v != f[u] && son[u] != v)
dfs2(v, v);
}
}

int ma[maxn<<2];
int mi[maxn<<2];
int lz[maxn<<2];
void pushup(int l, int r, int rt)
{
ma[rt] = max(ma[rt<<1], ma[rt<<1|1]);
mi[rt] = min(mi[rt<<1], mi[rt<<1|1]);
}
void build(int l, int r, int rt)
{
ma[rt] = 0;
mi[rt] = 0;
lz[rt] = 0;
if(l == r)
{
return;
}
int m = (l + r) >> 1;
build(l, m, rt<<1);
build(m+1, r, rt<<1|1);
}
void pushdown(int l, int r, int rt)
{
if(l == r)
return;
if(lz[rt])
{
mi[rt<<1] = -mi[rt<<1];
ma[rt<<1] = -ma[rt<<1];
swap(mi[rt<<1], ma[rt<<1]);
mi[rt<<1|1] = -mi[rt<<1|1];
ma[rt<<1|1] = -ma[rt<<1|1];
swap(mi[rt<<1|1], ma[rt<<1|1]);
lz[rt<<1] ^= 1;
lz[rt<<1|1] ^= 1;
lz[rt] = 0;
}
}
void update(int x, int y, int l, int r, int rt)
{
if(x == l && y == r)
{
mi[rt] = -mi[rt];
ma[rt] = -ma[rt];
swap(mi[rt], ma[rt]);
lz[rt] ^= 1;
return;
}
pushdown(l, r, rt);
int m = (l + r) >> 1;
if(y <= m)
update(x, y, l, m, rt<<1);
else if(x > m)
update(x, y, m+1, r, rt<<1|1);
else
{
update(x, m, l, m, rt<<1);
update(m+1, y, m+1, r, rt<<1|1);
}
pushup(l, r, rt);
}
void update2(int x, int l, int r, int rt, int w)
{
if(l == r)
{
ma[rt] = mi[rt] = w;
lz[rt] = 0;
return;
}
pushdown(l, r, rt);
int m = (l + r) >> 1;
if(x <= m)
update2(x, l, m, rt<<1, w);
else
update2(x, m+1, r, rt<<1|1, w);
pushup(l, r, rt);
}
int query(int x, int y, int l, int r, int rt)
{
if(l == x && r == y)
return ma[rt];
pushdown(l, r, rt);

int m = (l + r) >> 1;
if(y <= m)
return query(x, y, l, m, rt<<1);
else if(x > m)
return query(x, y, m+1, r, rt<<1|1);
else
{
return max(query(x, m, l, m, rt<<1), query(m+1, y, m+1, r, rt<<1|1));
}
}

void change(int u, int v)
{
while(top[u] != top[v])
{
if(dep[top[u]] < dep[top[v]])
swap(u, v);
update(tid[top[u]], tid[u], 1, n, 1);
u = f[top[u]];
}
if(u == v)
return;
if(dep[u] > dep[v])
swap(u, v);
update(tid[son[u]], tid[v], 1, n, 1);
}
int find(int u, int v)
{
int ans = -999999999;
while(top[u] != top[v])
{
if(dep[top[u]] < dep[top[v]])
swap(u, v);
ans = max(ans, query(tid[top[u]], tid[u], 1, n, 1));
u = f[top[u]];
}
if(u == v)
return ans;
if(dep[u] > dep[v])
swap(u, v);
ans = max(ans, query(tid[son[u]], tid[v], 1, n, 1));
return ans;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
init();

scanf("%d", &n);
for(int i = 1; i < n; i++)
{
int u, v, w;
scanf("%d %d %d", &u, &v, &w);
AddEdge(u, v);
d[i][0] = u;
d[i][1] = v;
d[i][2] = w;
}
dfs1(1, 0, 0);
dfs2(1, 1);
build(1, n, 1);

for(int i = 1; i < n; i++)
{
if(dep[d[i][0]] > dep[d[i][1]])
swap(d[i][0], d[i][1]);
update2(tid[d[i][1]], 1, n, 1, d[i][2]);
}
char s[10];
while(scanf("%s", s) && strcmp(s, "DONE"))
{
if(s[0] == 'Q')
{
int x, y;
scanf("%d %d", &x, &y);
printf("%d\n", find(x, y));
}
else if(s[0] == 'C')
{
int x, y;
scanf("%d %d", &x, &y);
update2(tid[d[x][1]], 1, n, 1, y);
}
else
{
int x, y;
scanf("%d %d", &x, &y);
change(x, y);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: