您的位置:首页 > 其它

poj 3237 Tree(树链剖分)

2017-11-07 23:12 357 查看
wa了半天。。懒惰标记那里要用异或来修改,wa的时候突然想到,万一两次反转相同的区间,反转就取消了,然而我的懒惰标记那里一直col[rt]=1,这样反转就没有取消。。。


#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

const int MAXN = 1e5+10;
const int INF = 0x3f3f3f3f;

struct Edge
{
int to,next;
} edge[MAXN*2];
int head[MAXN],tot;
int top[MAXN];
int fa[MAXN];
int deep[MAXN];
int num[MAXN];
int p[MAXN];
int fp[MAXN];
int son[MAXN];
int pos;

void init()
{
tot = 0;
memset(head,-1,sizeof(head));
pos = 1;
memset(son,-1,sizeof(son));
}
void addedge(int u,int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}

void dfs1(int u, int pre, int dep)
{
deep[u] = dep;
fa[u] = pre;
num[u] = 1;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(v == pre) continue;
dfs1(v,u,dep+1);
num[u] += num[v];
if(son[u] == -1 || num[v] > num[son[u]])
son[u] = v;
}
}

void getpos(int u, int sp)
{
top[u] = sp;
p[u] = pos++;
fp[p[u]] = u;
if(son[u] == -1) return;
getpos(son[u],sp);
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(v != son[u] && v != fa[u])
getpos(v,v);
}
}

int e[MAXN][3];
int n;
char op[15];
int maxn[MAXN<<2];
int minn[MAXN<<2];
int col[MAXN<<2];

void pushUp(int rt)
{
maxn[rt] = max(maxn[rt<<1], maxn[rt<<1|1]);
minn[rt] = min(minn[rt<<1], minn[rt<<1|1]);
}

void pushDown(int rt)
{
if(col[rt])
{
col[rt] = 0;
col[rt<<1] ^= 1;
col[rt<<1|1] ^= 1;
maxn[rt<<1] = -maxn[rt<<1];
minn[rt<<1] = -minn[rt<<1];
swap(maxn[rt<<1],minn[rt<<1]);
maxn[rt<<1|1] = -maxn[rt<<1|1];
minn[rt<<1|1] = -minn[rt<<1|1];
swap(maxn[rt<<1|1],minn[rt<<1|1]);
}
}

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

void updateTwo(int L, int R, int l, int r, int rt)
{
if(l >= L && r <= R)
{
maxn[rt] = -maxn[rt];
minn[rt] = -minn[rt];
swap(maxn[rt],minn[rt]);
col[rt] ^= 1;
return;
}
pushDown(rt);
int mid = (l+r) >> 1;
if(L <= mid) updateTwo(L,R,l,mid,rt<<1);
if(R > mid) updateTwo(L,R,mid+1,r,rt<<1|1);
pushUp(rt);
}

int query(int L, int R, int l, int r, int rt)
{
if(l >= L && r <= R)
return maxn[rt];
pushDown(rt);
int mid = (l+r) >> 1;
int ret = -INF;
if(L <= mid) ret = max(ret,query(L,R,l,mid,rt<<1));
if(R > mid) ret = max(ret,query(L,R,mid+1,r,rt<<1|1));
return ret;
}

int Calc(int u, int v)
{
int f1 = top[u],f2 = top[v];
int ret = -INF;
while(f1 != f2)
{
if(deep[f1] < deep[f2])
{
swap(f1,f2);
swap(u,v);
}
ret = max(ret,query(p[f1],p[u],1,n,1));
u = fa[f1];
f1 = top[u];
}
if(u == v) return ret;
if(deep[u] > deep[v]) swap(u,v);
ret = max(ret,query(p[son[u]],p[v],1,n,1));
return ret;
}

void flip(int u, int v)
{
int f1 = top[u],f2 = top[v];
while(f1 != f2)
{
if(deep[f1] < deep[f2])
{
swap(f1,f2);
swap(u,v);
}
updateTwo(p[f1],p[u],1,n,1);
u = fa[f1];
f1 = top[u];
}
if(u == v) return;
if(deep[u] > deep[v]) swap(u,v);
updateTwo(p[son[u]],p[v],1,n,1);
}

int main()
{
int T;
scanf("%d",&T);
while(T--)
{
init();
memset(maxn,0,sizeof(maxn));
memset(minn,0,sizeof(minn));
memset(col,0,sizeof(col));

scanf("%d",&n);
for(int i = 1; i < n; ++i)
{
scanf("%d %d %d",&e[i][0],&e[i][1],&e[i][2]);
addedge(e[i][0],e[i][1]);
addedge(e[i][1],e[i][0]);
}
dfs1(1,0,0);
getpos(1,1);
for(int i = 1; i < n; ++i)
{
if(deep[e[i][0]] > deep[e[i][1]])
swap(e[i][0],e[i][1]);
update(p[e[i][1]],e[i][2],1,n,1);
}
int u,v;
while(scanf("%s",op) && op[0] != 'D')
{
scanf("%d %d",&u,&v);
//最值查询
if(op[0] == 'Q')
printf("%d\n",Calc(u,v));
//单点修改
else if(op[0] == 'C')
update(p[e[u][1]],v,1,n,1);
//区间取相反数
else
flip(u,v);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: