您的位置:首页 > 其它

POJ 3237 Tree 树链剖分

2016-07-24 10:10 344 查看
【题意】给一颗树,有3种操作,第一种是修改一条边的权值,把a-b路径上的每一条边的边权改成相反的,还有查询2个点之前的最大权值。

【解题方法】算是比较裸的树剖了,一个基本的想法是用将边权变成点权,然后其他的就是最基本的剖分了,至于取反操作,每一个改变区间的最大最小,然后交换就可以等效这个操作了。很傻逼的是,我在单点更新没有pushdown导致wa无数发。

【AC 代码】

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 200010;
const int inf = 1e9;
struct edge
{
int to,next;
} E[maxn*3];
/***************************树链剖分******************************/
int head[maxn*2],tot,tim,n;
int e[maxn][3];
int siz[maxn],top[maxn],son[maxn];
int dep[maxn],Rank[maxn],tid[maxn],fa[maxn];
void Init()
{
memset(head,-1,sizeof(head));
memset(son,-1,sizeof(son));
tot=tim=0;
}
void addedge(int u,int v)
{
E[tot].to=v,E[tot].next=head[u],head[u]=tot++;
E[tot].to=u,E[tot].next=head[v],head[v]=tot++;
}

void dfs1(int u,int father,int d)
{
dep[u] = d;
fa[u] = father;
siz[u] = 1;
for(int i=head[u]; ~i; i=E[i].next)
{
int v = E[i].to;
if(v!=father)
{
dfs1(v,u,d+1);
if(son[u]==-1||siz[v]>siz[son[u]])
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=head[u]; ~i; i=E[i].next)
{
int v=E[i].to;
if(v!=fa[u]&&v!=son[u])
{
dfs2(v,v);
}
}
}
/****************************线段树*******************************/
struct node
{
int l,r;
int maxx,minn,ne;
} T[maxn<<2];
void pushup(int rt)
{
T[rt].maxx = max(T[rt*2].maxx,T[rt*2+1].maxx);
T[rt].minn = min(T[rt*2].minn,T[rt*2+1].minn);
}
void pushdown(int rt)
{
if(T[rt].ne)
{
T[rt<<1].maxx = -T[rt<<1].maxx;
T[rt<<1].minn = -T[rt<<1].minn;
swap(T[rt<<1].maxx,T[rt<<1].minn);
T[rt<<1|1].maxx = -T[rt<<1|1].maxx;
T[rt<<1|1].minn = -T[rt<<1|1].minn;
swap(T[rt<<1|1].maxx,T[rt<<1|1].minn);
T[rt<<1].ne ^=1;
T[rt<<1|1].ne ^=1;
T[rt].ne =0;
}
}
void Build(int l,int r,int rt)
{
T[rt].l=l,T[rt].r=r,T[rt].maxx=0,T[rt].minn=0,T[rt].ne=0;
if(l==r) return ;
int mid=(l+r)/2;
Build(l,mid,rt*2);
Build(mid+1,r,rt*2+1);
pushup(rt);
}
void update1(int pos,int val,int rt)//
{
if(T[rt].l==pos&&T[rt].r==pos)
{
T[rt].maxx=T[rt].minn=val;
T[rt].ne=0;
return ;
}
pushdown(rt);
int mid = (T[rt].l+T[rt].r)/2;
if(pos<=mid) update1(pos,val,rt*2);
else update1(pos,val,rt*2+1);
pushup(rt);
}
void update2(int L,int R,int rt)
{
if(L==T[rt].l&&T[rt].r==R)
{
T[rt].maxx = -T[rt].maxx;
T[rt].minn = -T[rt].minn;
swap(T[rt].maxx,T[rt].minn);
T[rt].ne^=1;
return ;
}
pushdown(rt);
int mid=(T[rt].l+T[rt].r)/2;
if(R<=mid) update2(L,R,rt*2);
else if(L>mid) update2(L,R,rt*2+1);
else
{
// update2(L,R,rt*2);
// update2(L,R,rt*2+1);
update2(L,mid,rt*2);
update2(mid+1,R,rt*2+1);
}
pushup(rt);
}
int query(int L,int R,int rt)
{
if(T[rt].l==L&&T[rt].r==R)
{
return T[rt].maxx;
}
pushdown(rt);
int mid=(T[rt].l+T[rt].r)/2;
if(R<=mid) return query(L,R,rt*2);
else if(L>mid) return query(L,R,rt*2+1);
else
{
// return max(query(L,R,rt*2),query(L,R,rt*2+1));
return max(query(L,mid,rt*2),query(mid+1,R,rt*2+1));
}
pushup(rt);
}
int lca(int x,int y)
{
int ans=-100000000;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans = max(ans,query(tid[top[x]],tid[x],1));
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
if(x!=y) ans=max(ans,query(tid[x]+1,tid[y],1));
return ans;
}
void Negate(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
update2(tid[top[x]],tid[x],1);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
if(x!=y) update2(tid[x]+1,tid[y],1);
}

int main()
{
int T;
scanf("%d",&T);
while(T--)
{
Init();
scanf("%d",&n);
for(int i=0; i<n-1; i++)
{
scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]);
addedge(e[i][0],e[i][1]);
}
dfs1(1,0,0);
dfs2(1,1);
Build(0,tim,1);
for(int i=0; i<n-1; i++)
{
if(dep[e[i][0]]>dep[e[i][1]]) swap(e[i][0],e[i][1]);
update1(tid[e[i][1]],e[i][2],1);
}
char op[10];
int u,v;
while(scanf("%s",op))
{
if(op[0]=='D') break;
scanf("%d%d",&u,&v);
if(op[0]=='Q')
{
printf("%d\n",lca(u,v));
}
else if(op[0]=='C')
{
update1(tid[e[u-1][1]],v,1);
}
else
Negate(u,v);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: