SPOJ375 Query on a tree

https://vjudge.net/problem/SPOJ-QTREE

题意:

一棵树,每条边有个权值

两种操作

一个修改每条边权值

一个询问两点之间这一条链的最大边权

点数<=10000

多组测试数据,case<=20

Example

Input:
1

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

Output:
1
3
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=210000;
const int inf=0x3fffffff;
int son[N],father[N],sz[N],head[N],num;
int ti[N],idx,dep[N],top[N];
struct edge{
    int ed,nxt;
}e[N*3];
struct Edge{
    int x,y,v;
}E[N*2];
int max(int a,int b){
    if(a>b)return a;
    return b;
}
void addedge(int x,int y){
    e[++num].ed=y;e[num].nxt=head[x];head[x]=num;
    e[++num].ed=x;e[num].nxt=head[y];head[y]=num;
}

void dfs_find(int u,int fa){//处理每棵子树大小和重儿子
    sz[u]=1;dep[u]=dep[fa]+1;son[u]=0;father[u]=fa;
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].ed;
        if(v==fa)continue;
        dfs_find(v,u);
        sz[u]+=sz[v];
        if(sz[son[u]]<sz[v])son[u]=v;
    }
}
void dfs_time(int u,int fa){
    ti[u]=idx++;
    top[u]=fa;
    if(son[u]!=0)dfs_time(son[u],top[u]);//处理同重链上点的top
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].ed;
        if(v==father[u]||v==son[u])continue;//枚举到了同一重链上的点就跳过
        dfs_time(e[i].ed,e[i].ed);
    }
}

struct tree{
    int l,r,v;
}T[N<<2];
void buildtree(int l,int r,int id){
    T[id].l=l;T[id].r=r;T[id].v=-inf;
    if(l==r)return;
    int mid=(l+r)>>1;
    buildtree(l,mid,id*2);
    buildtree(mid+1,r,id*2+1);
}
void update(int id,int cp,int v){
    if(T[id].l==T[id].r){T[id].v=v;return;}
    int mid=(T[id].l+T[id].r)>>1;
    if(mid>=cp)update(id*2,cp,v);
    if(mid<cp)update(id*2+1,cp,v);
    T[id].v=max(T[id*2].v,T[id*2+1].v);
}
int query(int l,int r,int id){
    if(T[id].r==r&&T[id].l==l)return T[id].v;
    int mid=(T[id].l+T[id].r)>>1;
    if(mid>=r)return query(l,r,id*2);
    else if(mid<l)return query(l,r,id*2+1);
    else return max(query(l,mid,id*2),query(mid+1,r,id*2+1));
}
int lca(int x,int y){
    int ans=-inf;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        ans=max(ans,query(ti[top[x]],ti[x],1));
        x=father[top[x]];
    }
    if(dep[x]>dep[y])swap(x,y);
    if(x!=y)ans=max(ans,query(ti[x]+1,ti[y],1));
    return ans;
}
int main(){
    int n,t,x,y,v,j;
    char str[100];
    scanf("%d",&t);
    while(t--){
        memset(head,0,sizeof(head));
        num=0;scanf("%d",&n);
        for(int i=1;i<n;i++){
            scanf("%d%d%d",&E[i].x,&E[i].y,&E[i].v);
            addedge(E[i].x,E[i].y);
        }
        dep[1]=0;sz[0]=0;idx=1;
        dfs_find(1,1);
        dfs_time(1,1);
        buildtree(2,n,1);
        for(int i=1;i<n;i++){
            if(dep[E[i].x]<dep[E[i].y])swap(E[i].x,E[i].y);
            update(1,ti[E[i].x],E[i].v);
        }
        while(true){
            scanf("%s",str);
            if(str[0]==‘D‘)break;
            else if(str[0]==‘Q‘){
                scanf("%d%d",&x,&y);
                printf("%d\n",lca(x,y));
            }
            else if(str[0]==‘C‘){
                scanf("%d%d",&j,&v);
                update(1,ti[E[j].x],v);
            }
        }
    }
    return 0;
}
时间: 2024-10-13 16:04:59

SPOJ375 Query on a tree的相关文章

SPOJ375 Query on a tree 树链剖分

SPOJ375  Query on a tree   树链剖分 no tags 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

spoj375 Query on a tree(树链剖分入门题)

#include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <queue> #include <map> #include <set> #include <vector> #include <cstdio> using namespace std; const int MAXN=10010

SPOJ375 Query on a tree经典入门题

剖分边更新,线段树点更新区间求极值.学树链剖分感觉还是先做点更细的好,而不是边更新.其实最主要还用来维护的数据结构了,剖分基本上都成模板了. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 #define lson l,m,rt<<1 6 #define rson m+1,r,rt<<1|1 7 const int m

spoj 375 Query on a tree (树链剖分)

Query on a tree 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 Q

【百度之星2014~复赛)解题报告】The Query on the Tree

声明 笔者最近意外的发现 笔者的个人网站http://tiankonguse.com/ 的很多文章被其它网站转载,但是转载时未声明文章来源或参考自 http://tiankonguse.com/ 网站,因此,笔者添加此条声明. 郑重声明:这篇记录<[百度之星2014~复赛)解题报告]The Query on the Tree>转载自 http://tiankonguse.com/ 的这条记录:http://tiankonguse.com/record/record.php?id=673 前言

[hdu 6191] Query on A Tree

Query on A Tree Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)Total Submission(s): 733    Accepted Submission(s): 275 Problem Description Monkey A lives on a tree, he always plays on this tree. One day, monkey

QTREE - Query on a tree

QTREE - Query on a tree 题目链接:http://www.spoj.com/problems/QTREE/ 参考博客:http://blog.sina.com.cn/s/blog_7a1746820100wp67.html 树链剖分入门题 代码如下(附注解): 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #define lson (x<<1) 5 #d

HDU 4836 The Query on the Tree lca || 欧拉序列 || 动态树

lca的做法还是很明显的,简单粗暴, 不过不是正解,如果树是长链就会跪,直接变成O(n).. 最后跑的也挺快,出题人还是挺阳光的.. 动态树的解法也是听别人说能ac的,估计就是放在splay上剖分一下,做法还是比较复杂的,,, 来一发lca: #include <stdio.h> #include <iostream> #include <algorithm> #include <sstream> #include <stdlib.h> #inc

SPOJ QTREE 375. Query on a tree

SPOJ Problem Set (classical) 375. Query on a tree Problem 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: CHA