Ural1553 Caves and Tunnels 树链剖分

科学家使用机器人探索火星表面发现的洞穴系统,并通过编写程序解决如何实时监测洞穴间放射水平的问题,确保机器人安全移动。

首先用树链剖分,将一颗树按轻重链划分成多条链。然后加每一个链从深度由高到底,组成一个有序序列,然后用线段树维护即可。

操作。

I i d 将节点i增加d
G i j 查找i与j之间路径上的最大值。

1553. Caves and Tunnels

Time limit: 3.0 second
Memory limit: 64 MB
After landing on Mars surface, scientists found a strange system of caves connected by tunnels. So they began to research it using remote controlled robots. It was found out that there exists exactly one route between every pair of caves. But then scientists faced a particular problem. Sometimes in the caves faint explosions happen. They cause emission of radioactive isotopes and increase radiation level in the cave. Unfortunately robots don't stand radiation well. But for the research purposes they must travel from one cave to another. So scientists placed sensors in every cave to monitor radiation level in the caves. And now every time they move robots they want to know the maximal radiation level the robot will have to face during its relocation. So they asked you to write a program that will solve their problem.

Input

The first line of the input contains one integer N (1 ≤ N ≤ 100000) — the number of caves. NextN − 1 lines describe tunnels. Each of these lines contains a pair of integers aibi(1 ≤ aibi ≤ N) specifying the numbers of the caves connected by corresponding tunnel. The next line has an integer Q (Q ≤ 100000) representing the number of queries. The Q queries follow on a single line each. Every query has a form of "C U V", where C is a single character and can be either 'I' or 'G' representing the type of the query (quotes for clarity only). In the case of an 'I' query radiation level in U-th cave (1 ≤ U ≤ N) is incremented by V (0 ≤ V ≤ 10000). In the case of a 'G' query your program must output the maximal level of radiation on the way between caves with numbers U and V (1 ≤ UV ≤ N) after all increases of radiation ('I' queries) specified before current query. It is assumed that initially radiation level is 0 in all caves, and it never decreases with time (because isotopes' half-life time is much larger than the time of observations).

Output

For every 'G' query output one line containing the maximal radiation level by itself.

Sample

input output
4
1 2
2 3
2 4
6
I 1 1
G 1 1
G 3 4
I 2 3
G 1 1
G 3 4 
1
0
1
3


#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>

using namespace std;

#define INF 0x3ffffff
#define MAXN 100010

struct node
{
    int to,next;
}edge[9999999];

int head[MAXN],en;
int belong[MAXN],idx[MAXN],qid[MAXN],fi[MAXN];
int top[MAXN],len[MAXN];
int dep[MAXN],fat[MAXN],size[MAXN];
int Q[MAXN],vis[MAXN];
int n,cnt;

void add(int u,int v)
{
    edge[en].to=v;
    edge[en].next=head[u];
    head[u]=en++;
}

void split()
{
    int l,r;
    memset(dep,-1,sizeof(dep));
    l=0;
    dep[Q[r=1]=1]=0;
    fat[1]=-1;
    while(l<r)
    {
        int x=Q[++l];
        vis[x]=0;
        for(int y=head[x];y!=-1;y=edge[y].next)
            if(dep[edge[y].to]==-1)
            {
                dep[Q[++r]=edge[y].to]=dep[x]+1;
                fat[edge[y].to]=x;
            }
    }
    cnt=0;
    for(int i=n;i;i--)
    {
        int x=Q[i],p=-1;
        size[x]=1;
        for(int y=head[x];y!=-1;y=edge[y].next)
            if(vis[edge[y].to])
            {
                size[x]+=size[edge[y].to];
                if(p==-1||size[edge[y].to]>size[p])
                    p=edge[y].to;
            }
        if(p==-1)
        {
            idx[x]=len[++cnt]=1;
            belong[top[cnt]=x]=cnt;
        }
        else
        {
            idx[x]=++len[belong[x]=belong[p]];
            top[belong[x]]=x;
        }
        vis[x]=true;
    }
}

void getqid()
{
    fi[1]=1;
    for(int i=2;i<=cnt;i++)
        fi[i]=fi[i-1]+len[i-1];
    for(int i=1;i<=n;i++)
    {
        int blo=belong[i];
        qid[i]=fi[blo]+len[blo]-idx[i];
    }
}


int query(int l,int r,int root,int L,int R);
int research(int x,int y)
{
    int ret=-INF;
    while(belong[x]!=belong[y])
    {
        if(dep[top[belong[x]]]<dep[top[belong[y]]])
            swap(x,y);
        ret=max(query(1,n,1,qid[top[belong[x]]],qid[x]),ret);
        x=fat[top[belong[x]]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    ret=max(query(1,n,1,qid[x],qid[y]),ret); 
    return ret;
}

#define lson l,m,root<<1
#define rson m+1,r,root<<1|1

int node[MAXN<<2];

void push_up(int root)
{
    node[root]=max(node[root<<1],node[root<<1|1]);
}

void build(int l,int r,int root)
{
    if(l==r)
    {
        node[root]=0;
        return ;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    push_up(root);
}

void update(int l,int r,int root,int a,int d)
{
    if(l==r)
    {
        node[root]+=d;
        return ;
    }
    int m=(l+r)>>1;
    if(a<=m)
        update(lson,a,d);
    else
        update(rson,a,d);
    push_up(root);
}

int query(int l,int r,int root,int L,int R)
{
    if(l>=L && r<=R)
        return node[root];
    int m=(l+r)>>1;
    int ret=-INF;
    if(L<=m)
        ret=max(ret,query(lson,L,R));
    if(R>m)
        ret=max(ret,query(rson,L,R));
    return ret;
}


int main()
{
    while(~scanf("%d",&n))
    {
        memset(head,-1,sizeof(head));
        en=0;
        int u,v;
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        split();
        getqid();
        build(1,n,1);
        int m;
        scanf("%d",&m);
        char que[3];
        for(int i=0;i<m;i++)
        {
            scanf("%s",que);
            if(que[0]=='G')
            {
                scanf("%d%d",&u,&v);
                printf("%d\n",research(u,v));
            }
            else
            {
                scanf("%d%d",&u,&v);
                update(1,n,1,qid[u],v);
            }

        }


    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值