您的位置:首页 > 其它

poj3237

2015-07-06 00:47 211 查看
这题同样是要将边权下放到点

这题要注意的是negate询问,是将权值取反,因为是区间修改,要用到laze标记

但是要注意的是,如果有标记下放的时候,如果下边已经有标记了, 那么就是取反,再取反, 所以只要将标记去除就行了

就因为这个wa了好几发

同时,线段树也要维护一个最小值,因为取反之后,最小值就变成最大值了

#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>
#pragma warning(disable:4996)
#pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
const int INF = 1<<30;

const int N = 100000 + 10;
int size
, fa
, depth
, son
, w
, top
, num;
int Max[N * 4], Min[N * 4];
int col[N * 4];
std::vector<int> g
;
int edge
[3];
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])
{
depth[v] = depth[u] + 1;
fa[v] = u;
dfs(v);
size[u] += size[v];
if (size[v]>size[son[u]])
son[u] = v;
}
}
}

void dfs2(int u, int tp)
{
w[u] = ++num;
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 != son[u] && v != fa[u])
dfs2(v, v);
}

}

void pushUp(int rt)
{
Max[rt] = std::max(Max[rt << 1], Max[rt << 1 | 1]);
Min[rt] = std::min(Min[rt << 1], Min[rt << 1 | 1]);
}
void pushDown(int rt)
{
if (col[rt])
{
//col[rt << 1] = col[rt << 1 | 1] = col[rt];
// 注意标记的下放
col[rt << 1] ^= 1;
col[rt << 1 | 1] ^= 1;
int tmp = Max[rt << 1];
Max[rt << 1] = -Min[rt << 1];
Min[rt << 1] = -tmp;
tmp = Max[rt << 1 | 1];
Max[rt << 1 | 1] = -Min[rt << 1 | 1];
Min[rt << 1 | 1] = -tmp;
col[rt] = 0;
}
}
void change(int l, int r, int rt, int pos, int val)
{
pushDown(rt);
if (l == r)
{
Min[rt] = Max[rt] = val;
return;
}
int mid = (l + r) >> 1;
if (pos <= mid)
change(l, mid, rt << 1, pos, val);
else
change(mid + 1, r, rt << 1 | 1, pos, val);
pushUp(rt);
}

void negate(int l, int r, int rt, int L, int R)
{
pushDown(rt);
if (L <= l && R >= r)
{
int tmp = Max[rt];
Max[rt] = -Min[rt];
Min[rt] = -tmp;
col[rt] = 1;
return;
}
int mid = (l + r) >> 1;
if (L <= mid)
negate(l, mid, rt << 1, L, R);
if (R > mid)
negate(mid + 1, r, rt << 1 | 1, L, R);
pushUp(rt);
}
int ans ;
void query(int l, int r, int rt, int L, int R)
{
pushDown(rt);
if (L <= l && R >= r)
{
ans = std::max(ans, Max[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);
pushUp(rt);
}
int main()
{
//freopen("d:/in.txt", "r", stdin);
int t, n, a, b;
char op[11];
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
g[i].clear();
memset(col, 0, sizeof(col));
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]);
}
depth[1] = fa[1] = 0;
dfs(1);
dfs2(1, 1);
for (int i = 1; i < n; ++i)
{
if (depth[edge[i][0]] > depth[edge[i][1]])
std::swap(edge[i][0], edge[i][1]);
change(1, n, 1, w[edge[i][1]], edge[i][2]);
}
while (true)
{
scanf("%s", op);
if (op[0] == 'D')
break;
scanf("%d%d", &a, &b);
if (op[0] == 'Q')
{
ans = -INF;
while (top[a] != top[b])
{
if (depth[top[a]] < depth[top[b]])
std::swap(a, b);
query(1, n, 1, w[top[a]], w[a]);
a = fa[top[a]];
}
if (a == b)
{
printf("%d\n", ans);
continue;
}
if (depth[a]>depth[b])
std::swap(a, b);
query(1, n, 1, w[son[a]], w[b]);
printf("%d\n", ans);
}
else if (op[0] == 'C')
{
change(1, n, 1, w[edge[a][1]], b);
}
else
{
while (top[a] != top[b])
{
if (depth[top[a]] < depth[top[b]])
std::swap(a, b);
negate(1, n, 1, w[top[a]], w[a]);
a = fa[top[a]];
}
if (a == b)
continue;
if (depth[a]>depth[b])
std::swap(a, b);
negate(1, n, 1, w[son[a]], w[b]);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: