您的位置:首页 > 其它

FZU2082

2015-07-06 00:39 183 查看
树链剖分后要处理的是边的权值,而不是点的权值,但是只要边权下放到点,就可以了

如图

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <math.h>
using namespace std;
#pragma warning(disable:4996)
#pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
const int INF = 1<<30;
/*
12 1
1 2 1
2 3 1
3 4 1
4 5 1
5 11 1
11 12 1
1 6 1
6 7 1
7 8 1
6 9 1
6 10 1
1 9 10
*/
const int N = 50000 + 10;
vector<int> g
;
int size
, son
, fa
, depth
, top
, w
, num, ra
;
LL tree[N*4];
int edge
[3];
int h
;
void dfs(int u)
{
size[u] = 1;
son[u] = 0;
for (int i = 0; i < g[u].size(); ++i)
{
int v = g[u][i];
if (v != fa[u])
{
fa[v] = u;
depth[v] = depth[u] + 1;
dfs(v);
size[u] += size[v];
if (size[v] > size[son[u]])
son[u] = v;
}
}
}

void dfs2(int u, int tp)
{
w[u] = ++num;
ra[num] = u;
top[u] = tp;
if (son[u] != 0)
dfs2(son[u], top[u]);
for (int i = 0; i < g[u].size(); ++i)
{
int v = g[u][i];
if (v != fa[u] && v != son[u])
dfs2(v, v);
}

}
void pushUp(int rt)
{
tree[rt] = tree[rt << 1] + tree[rt << 1 | 1];
}
void update(int l, int r, int rt, int pos, int val)
{
if (l == r)
{
tree[rt] = val;
return;
}
int mid = (l + r) >> 1;
if (pos <= mid)
update(l, mid, rt << 1, pos, val);
else
update(mid + 1, r, rt << 1 | 1, pos, val);
pushUp(rt);
}

LL ans;
void query(int l, int r, int rt, int L, int R)
{
if (L <= l&&R >= r)
{
ans += tree[rt];
return;
}
int mid = (l + r) >> 1;
if (L <= mid)
query(l, mid, rt << 1, L, R);
if (R > mid)
query(mid + 1, r, rt << 1 | 1, L, R);
}
int main()
{
int n, m, a, b, c;
while (scanf("%d%d", &n, &m) != EOF)
{
memset(tree, 0, sizeof(tree));
for (int i = 1; i <= n; ++i)
g[i].clear();
num = 0;
for (int i = 1; i < n; ++i)
{
scanf("%d%d%d", &edge[i][0], &edge[i][1], &edge[i][2]);
g[edge[i][0]].push_back(edge[i][1]);
g[edge[i][1]].push_back(edge[i][0]);
}
fa[1] = depth[1] = 0;
dfs(1);
dfs2(1, 1);
for (int i = 1; i < n; ++i)
{
if (depth[edge[i][0]] > depth[edge[i][1]])
swap(edge[i][0], edge[i][1]);
h[edge[i][1]] = edge[i][2];
update(1, n, 1, w[edge[i][1]], edge[i][2]);
}
while (m--)
{
scanf("%d%d%d", &a, &b, &c);
if (a == 0)
{
if (depth[edge[b][0]] > depth[edge[b][1]])
swap(edge[b][0], edge[b][1]);
update(1, n, 1, w[edge[b][1]], c);
h[edge[b][1]] = c;
}
else
{
ans = 0;
while (top[b] != top[c])
{
if (depth[top[b]] < depth[top[c]])
swap(b, c);
query(1, n, 1, w[top[b]], w[b]);
b = fa[top[b]];
}
//b和c一定是在一条链上
if (depth[b]>depth[c])
swap(b, c);

//如果b有父亲,那么就有边下放到它,多加了这个点,要减去
query(1, n, 1, w[b], w[c]);
if (fa[b] != 0)
ans -= h[b];
/*
如果b,c是在一条重链上, 那么询问w[son[b]] 到w[c]
那么就没有加到点b
否则,b,c就是指向同一点,那么w[son[b]] > w[c] , 询问是不会增加任何值的
query(1, n, 1, w[son[b]], w[c]);
*/
printf("%lld\n", ans);
}
}
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: