375. Query on a treeProblem code: QTREE |
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1.
We will ask you to perfrom some instructions of the following form:
The first line of input contains an integer t, the number of test cases (t <= 20). t test cases follow.
For each test case:
There is one blank line between successive tests.
For each "QUERY" operation, write one integer representing its result.
Input: 1 3 1 2 1 2 3 2 QUERY 1 2 CHANGE 1 3 QUERY 1 2 DONE Output: 1 3
题意:
给你一颗树。然后你可以对这个树就行两种操作。
1.修改某条边的边权。
2.查询u->v路径上。最大的边权。
题目链接点击打开链接
思路:
没学树链剖分前,觉得这个算法比较难,学了下发现没有想象的那么难。
讲解见点击打开链接还是蛮浅显易懂的。
#include
#include
#include
#include
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=10010;
typedef long long ll;
#define lson L,mid,ls
#define rson mid+1,R,rs
int fa[maxn],dep[maxn],sz[maxn],son[maxn], id[maxn],top[maxn],cnt,ptr;
//记sz[u]表示以u为根的子树的节点数,dep[u]表示u的深度(根深度为1),top[u]表示u所在的重链的顶端节点,
//fa[u]表示u的父亲,son[u]表示与u在同一重链上的u的儿子节点(姑且称为重儿子),id[u]表示u与其父亲节点的连边(姑且称为u的父边)在线段树中的位置。
struct node
{
int v;
node *next;
} ed[maxn<<1],*head[maxn];
int mav[maxn<<2],uu[maxn],vv[maxn],wei[maxn];
void build(int L,int R,int rt)
{
mav[rt]=-INF;
if(L==R)
return;
int ls=rt<<1,rs=ls|1,mid=(L+R)>>1;
build(lson);
build(rson);
}
void update(int L,int R,int rt,int p,int d)
{
if(L==R)
{
mav[rt]=d;
return;
}
int ls=rt<<1,rs=ls|1,mid=(L+R)>>1;
if(p<=mid)
update(lson,p,d);
else
update(rson,p,d);
mav[rt]=max(mav[ls],mav[rs]);
}
int qu(int L,int R,int rt,int l,int r)
{
if(l<=L&&R<=r)
return mav[rt];
int ls=rt<<1,rs=ls|1,mid=(L+R)>>1,tp=-INF;
if(l<=mid)
tp=max(tp,qu(lson,l,r));
if(r>mid)
tp=max(tp,qu(rson,l,r));
return tp;
}
void adde(int u,int v)
{
ed[cnt].v=v;
ed[cnt].next=head[u];
head[u]=&ed[cnt++];
}
void dfs(int u)
{
int v,ms=-INF;
sz[u]=1,son[u]=-1;
for(node *p=head[u];p!=NULL;p=p->next)
{
v=p->v;
if(v==fa[u])
continue;
fa[v]=u;
dep[v]=dep[u]+1;
dfs(v);
if(sz[v]>ms)
ms=sz[v],son[u]=v;
sz[u]+=sz[v];
}
}
void getid(int u,int ft)
{
id[u]=++ptr,top[u]=ft;
if(son[u]!=-1)
getid(son[u],top[u]);
for(node *p=head[u];p!=NULL;p=p->next)
{
if(p->v==fa[u]||p->v==son[u])
continue;
getid(p->v,p->v);
}
}
void init(int rt)
{
fa[rt]=-1;
dep[rt]=ptr=0;
dfs(rt);
getid(rt,rt);//根没有父边。但是在线段树中占了1的位置。但是不会用到。只是写起来方便
build(1,ptr,1);//1-ptr。ptr条边。是算上根的虚拟边的。
}
inline int calc(int u,int v)
{
int f1=top[u],f2=top[v],tp=-INF;
while(f1!=f2)
{
if(dep[f1]dep[v])
swap(u,v);
tp=max(tp,qu(1,ptr,1,id[son[u]],id[v]));
return tp;
}
int main()
{
int n,u,v,w,t,rt,i;
char cmd[100];
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
rt=(n+1)/2;
cnt=0;
memset(head,0,sizeof head);
for(i=1;idep[vv[i]])
swap(uu[i],vv[i]);
update(1,ptr,1,id[vv[i]],wei[i]);
}
while(1)
{
scanf("%s",cmd);
if(cmd[0]=='D')
break;
scanf("%d%d",&u,&v);
if(cmd[0]=='C')
update(1,ptr,1,id[vv[u]],v);
else
printf("%d\n",calc(u,v));
}
}
return 0;
}