您的位置:首页 > 运维架构

树链剖分-链的剖分(线段树维护边权值的更新)

2014-08-04 19:50 274 查看
poj3237

Tree

Time Limit: 5000MSMemory Limit: 131072K
Total Submissions: 3629Accepted: 1017
Description

You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions
can be one of the following forms:

CHANGE
i v
Change the weight of the ith edge to v
NEGATE
a b
Negate the weight of every edge on the path from a to b
QUERY
a b
Find the maximum weight of edges on the path from a to b
Input

The input contains multiple test cases. The first line of input contains an integer t (t ≤ 20), the number of test cases. Then follow the test cases.

Each test case is preceded by an empty line. The first nonempty line of its contains N (N ≤ 10,000). The next N − 1 lines each contains three integers a, b and c, describing an edge connecting nodes a and bwith
weight c. The edges are numbered in the order they appear in the input. Below them are the instructions, each sticking to the specification above. A lines with the word “
DONE
” ends the test case.

Output

For each “
QUERY
” instruction, output the result on a separate line.

Sample Input

1

3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE

Sample Output

1
3


题意:给出一颗树以及边权值,对边权有三种操作:(1)把第i条边的权值改成v;(2)把<u,v>路径上的边权值改为原来的相反数;(3)输出[b]<u,v>路径上的最大权值;[/b]

[b]程序:[/b]



#include"stdio.h"
#include"string.h"
#include"iostream"
#include"map"
#include"string"
#include"queue"
#include"stdlib.h"
#include"math.h"
#define M 11009
#define eps 1e-10
#define inf 1000000000
#define mod 1000000000
#define INF 1000000000
using namespace std;
struct node
{
int u,v,w,next;
}edge[M*2];
int t,head[M];
int son[M];//记录重链中某点的儿子节点,子叶节点的儿子为-1;
int fa[M];//记录每个节点的父节点;
int num[M];//记录以该节点为根的子树中有多少个节点;
int top[M];//记录某条重链中所有节点的最初节点编号;
int p[M];//记录某个节点的编号(对原来的节点重新编号)
int fp[M];//记录某编号的节点对应的原来的节点编号;
int deep[M];//记录某个节点在树中的深度;
int a[M];//记录编过号的节点与其父节点之间的边的边权值;维护的线段树是n-1个点
int pos;
int Max;
void init()
{
t=pos=0;
memset(head,-1,sizeof(head));
memset(son,-1,sizeof(son));
}
void add(int u,int v)
{
edge[t].u=u;
edge[t].v=v;
edge[t].next=head[u];
head[u]=t++;
}
void dfs(int u,int f,int d)
{
deep[u]=d;
num[u]=1;
fa[u]=f;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(v!=f)
{
dfs(v,u,d+1);
num[u]+=num[v];
if(son[u]==-1||num[son[u]]<num[v])
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].v;
if(v!=fa[u]&&v!=son[u])
getpos(v,v);
}
}//以上是求重链
//***************************以下是线段树操作****************************//
struct Node
{
int l,r,flag,maxi,mini;
}tree[M*4];
void pushup(int i)
{
tree[i].maxi=max(tree[i*2].maxi,tree[i*2+1].maxi);
tree[i].mini=min(tree[i*2].mini,tree[i*2+1].mini);
}
void pushdown(int i)//lazy操作
{
if(tree[i].l==tree[i].r)return;
if(tree[i].flag)
{
tree[i*2].maxi=-tree[i*2].maxi;
tree[i*2].mini=-tree[i*2].mini;
swap(tree[i*2].maxi,tree[i*2].mini);
tree[i*2].flag^=1;
tree[i*2+1].maxi=-tree[i*2+1].maxi;
tree[i*2+1].mini=-tree[i*2+1].mini;
swap(tree[i*2+1].maxi,tree[i*2+1].mini);
tree[i*2+1].flag^=1;
tree[i].flag=0;
}
}
void make(int l,int r,int i)//建立线段树
{
tree[i].l=l;
tree[i].r=r;
tree[i].flag=0;
if(tree[i].l==tree[i].r)
{
tree[i].maxi=tree[i].mini=a[tree[i].l];
return;
}
int mid=(l+r)>>1;
make(l,mid,i*2);
make(mid+1,r,i*2+1);
pushup(i);
}
void change(int p,int q,int i)//单点更新
{
if(tree[i].l==p&&tree[i].r==p)
{
tree[i].maxi=tree[i].mini=q;
tree[i].flag=0;
return;
}
pushdown(i);
int mid=(tree[i].l+tree[i].r)>>1;
if(p<=mid)change(p,q,i*2);
else change(p,q,i*2+1);
pushup(i);
}
void negval(int l,int r,int i)//区间修改为相反数
{
if(tree[i].l==l&&tree[i].r==r)
{
tree[i].maxi=-tree[i].maxi;
tree[i].mini=-tree[i].mini;
swap(tree[i].maxi,tree[i].mini);
tree[i].flag^=1;
return;
}
pushdown(i);
int mid=(tree[i].l+tree[i].r)>>1;
if(r<=mid)
negval(l,r,i*2);
else if(l>mid)
negval(l,r,i*2+1);
else
{
negval(l,mid,i*2);
negval(mid+1,r,i*2+1);
}
pushup(i);
}
void query(int l,int r,int i)//区间查找
{
if(tree[i].l==l&&tree[i].r==r)
{
Max=max(Max,tree[i].maxi);
return;
}
pushdown(i);
int mid=(tree[i].l+tree[i].r)>>1;
if(r<=mid)
query(l,r,i*2);
else if(l>mid)
query(l,r,i*2+1);
else
{
query(l,mid,i*2);
query(mid+1,r,i*2+1);
}
pushup(i);
}
int findmax(int u,int v)//树形图转换为线段树结构,并查找最大值
{
int f1=top[u];
int f2=top[v];
int ans=-inf;
while(f1!=f2)
{
if(deep[f1]<deep[f2])
{
swap(f1,f2);
swap(u,v);
}
Max=-inf;
query(p[f1],p[u],1);
ans=max(ans,Max);
u=fa[f1];
f1=top[u];
}
if(v==u)return ans;
if(deep[u]>deep[v])swap(u,v);
Max=-inf;
query(p[son[u]],p[v],1);
ans=max(ans,Max);
return ans;
}
void neg(int u,int v)//树形图转换为线段树结构,并修改区间值
{
int f1=top[u];
int f2=top[v];
while(f1!=f2)
{
if(deep[f1]<deep[f2])
{
swap(f1,f2);
swap(u,v);
}
negval(p[f1],p[u],1);
u=fa[f1];
f1=top[u];
}
if(v==u)return;
if(deep[u]>deep[v])swap(u,v);
negval(p[son[u]],p[v],1);
return;
}
struct Edge
{
int u,v,w;
}e[M];
int main()
{
int T,i,n;
cin>>T;
while(T--)
{
scanf("%d",&n);
init();
for(i=1;i<n;i++)
{
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
add(e[i].u,e[i].v);
add(e[i].v,e[i].u);
}
dfs(1,1,0);
getpos(1,1);
for(i=1;i<n;i++)
{
if(deep[e[i].u]<deep[e[i].v])
swap(e[i].v,e[i].u);
a[p[e[i].u]]=e[i].w;
}
make(1,pos-1,1);
char ch[22];
int x,y;
while(scanf("%s",ch),strcmp(ch,"DONE")!=0)
{
scanf("%d%d",&x,&y);
if(ch[0]=='Q')
{
printf("%d\n",findmax(x,y));
}
else if(ch[0]=='C')
{
change(p[e[x].u],y,1);
}
else
neg(x,y);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: