SPOJ

来源:互联网 发布:淘宝左右香水是正品吗 编辑:程序博客网 时间:2024/06/06 01:16

传送门:http://www.spoj.com/problems/QTREE/en/

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:

  • CHANGE i ti : change the cost of the i-th edge to ti
    or
  • QUERY a b : ask for the maximum edge cost on the path from node a to node b

Input

The first line of input contains an integer t, the number of test cases (t <= 20). t test cases follow.

For each test case:

  • In the first line there is an integer N (N <= 10000),
  • In the next N-1 lines, the i-th line describes the i-th edge: a line with three integers a b c denotes an edge between ab of cost c (c <= 1000000),
  • The next lines contain instructions "CHANGE i ti" or "QUERY a b",
  • The end of each test case is signified by the string "DONE".

There is one blank line between successive tests.

Output

For each "QUERY" operation, write one integer representing its result.

Example

Input:131 2 12 3 2QUERY 1 2CHANGE 1 3QUERY 1 2DONEOutput:13
题目大意:

有一个n个点,n-1条边的树,每条边有一个权值,然后有两种操作:(1)更改第a条边的权值为b,(2)查询节点a到b之前边的权值最大是多少。

题解:

第一次写树链剖分,学习的大牛们的博客,按着整个剖分的思路谢了一遍,感觉理论还是比较好理解的,然后再套上线段树就是了。对于这个题,只要会了树链剖分的理论知识就可以写了。关于熟练剖分的知识讲解在这就不赘述了,毕竟笔者的逻辑和叙述能力很菜。

注意边所对应的点是哪一个,然后就是点怎么映射到线段树上。

自己看过的博客(最好找一个入门题然后按着被别人的代码写一遍有利于更好更快的理解):

http://blog.csdn.net/y990041769/article/details/40348013

http://www.tuicool.com/articles/ee2QZf6

http://www.cnblogs.com/sagitta/p/5660749.html

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>using namespace std;struct node{    int u,v,w;    int nex;}eage[20005];int head[20005],cnt;int siz[20005],top[20005],son[20005],fa[20005];int deep[20005],id[20005],idx,Max[50005],val[20005];void init(){    memset(head,-1,sizeof(head));    cnt=0;}void ADD(int u,int v,int w){    eage[cnt].u=u;    eage[cnt].v=v;    eage[cnt].w=w;    eage[cnt].nex=head[u];    head[u]=cnt++;}void build(int u,int l,int r){    if(l==r)    {        Max[u]=val[l];        return ;    }    int mid=(l+r)>>1;    build(u<<1,l,mid);    build(u<<1|1,mid+1,r);    Max[u]=max(Max[u<<1],Max[u<<1|1]);}void dfs1(int x,int f,int dep){    deep[x]=dep;    fa[x]=f;    siz[x]=1;    son[x]=0;    for(int i=head[x];i!=-1;i=eage[i].nex)    {        int y=eage[i].v;        if(y==f)continue;        dfs1(y,x,dep+1);        siz[x]+=siz[y];        if(siz[son[x]]<siz[y])        {            son[x]=y;        }    }}void dfs2(int u,int tp){    top[u]=tp;    id[u]=++idx;    if(son[u])dfs2(son[u],tp);    for(int i=head[u];i!=-1;i=eage[i].nex)    {        int v=eage[i].v;        if(v==fa[u]||v==son[u])continue;        dfs2(v,v);    }}int query(int u,int l,int r,int L,int R){    //cout<<"*"<<l<<" "<<r<<" "<<L<<" "<<R<<endl;    if(L<=l&&r<=R)return Max[u];    int mid=(l+r)>>1;    int ans=0;    if(L<=mid)ans=max(ans,query(u<<1,l,mid,L,R));    if(R>mid)ans=max(ans,query(u<<1|1,mid+1,r,L,R));    return ans;}int work(int u,int v){    int tp1=top[u],tp2=top[v];    //cout<<tp1<<" "<<tp2<<endl;    int ans=0;    while(tp1!=tp2)    {        if(deep[tp1]<deep[tp2])        {            swap(tp1,tp2);            swap(u,v);///从u往上升        }        ans=max(ans,query(1,1,idx,id[tp1],id[u]));        u=fa[tp1];        tp1=top[u];    }    //cout<<u<<" "<<v<<endl;    //cout<<deep[u]<<" "<<deep[v]<<endl;    if(u==v)return ans;    if(deep[u]>deep[v])swap(u,v);    //cout<<id[son[u]]<<" "<<id[v]<<endl;    ans=max(ans,query(1,1,idx,id[son[u]],id[v]));    return ans;}void change(int u,int l,int r,int pos,int c){    if(l==r&&l==pos)    {        Max[u]=c;        return;    }    int mid=(l+r)>>1;    if(pos<=mid)change(u<<1,l,mid,pos,c);    else change(u<<1|1,mid+1,r,pos,c);    Max[u]=max(Max[u<<1],Max[u<<1|1]);}int main(){    int T;    scanf("%d",&T);    int a,b,c;    while(T--)    {        int n;        scanf("%d",&n);        init();        for(int i=1;i<n;i++)        {            scanf("%d%d%d",&a,&b,&c);            ADD(a,b,c);            ADD(b,a,c);        }        idx=0;        dfs1(1,0,1);        dfs2(1,1);        //cout<<"debug"<<endl;        for(int i=0;i<cnt;i+=2)        {            if(deep[eage[i].u]<deep[eage[i].v])swap(eage[i].u,eage[i].v);            val[id[eage[i].u]]=eage[i].w;        }        build(1,1,idx);//        for(int i=0;i<=idx;i++)cout<<" "<<val[i];//        cout<<endl;        char s[10];        while(1)        {            scanf("%s",s);            if(strcmp(s,"DONE")==0)break;            scanf("%d%d",&a,&b);            if(s[0]=='Q')            {                printf("%d\n",work(a,b));            }            else if(s[0]=='C')            {                a--;                change(1,1,idx,id[eage[2*a].u],b);            }        }        cout<<endl;    }    return 0;}


原创粉丝点击