SPOJ QTREE - Query on a tree

Description

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:
1

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

Output:
1
3

本来应该写树链剖分的,但既然要练LCT就敲敲咯……也是调了蛮久

#include<cstdio>
#include<cstring>
#include<algorithm>
#define MN 10010
using namespace std;

int p,ca,f;
inline int read(){
    p=0;ca=getchar();f=1;
    while(ca<‘0‘||ca>‘9‘) {if (ca==‘-‘) f=-1;ca=getchar();}
    while(ca>=‘0‘&&ca<=‘9‘) p=p*10+ca-48,ca=getchar();
    return p*f;
}
struct na{
    int y,ne,c,nu;
}b[MN*2];
int fa[MN],n,t,x,y,c,l[MN],r[MN],num,id[MN],key[MN],ch[MN][2],ma[MN];
bool rt[MN];
inline int max(int a,int b){return a>b?a:b;}
inline void update(int x){
    ma[x]=max(max(ma[ch[x][0]],ma[ch[x][1]]),key[x]);
}
inline void rot(int x){
    int y=fa[x],kind=ch[y][1]==x;
    fa[x]=fa[y];
    fa[y]=x;
    ch[y][kind]=ch[x][!kind];
    fa[ch[y][kind]]=y;
    ch[x][!kind]=y;
    if(rt[y]) rt[y]=0,rt[x]=1;else ch[fa[x]][ch[fa[x]][1]==y]=x;
    update(y);update(x);
}
inline void splay(int x){
    while(!rt[x]){
        if (rt[fa[x]]) rot(x);else
        if ((ch[fa[fa[x]]][1]==fa[x])==(ch[fa[x]][1]==x)) rot(fa[x]),rot(x);else rot(x),rot(x);
    }
}
inline void acc(int u){
    int x=0;
    while(u){
        splay(u);
        rt[ch[u][1]]=1;rt[ch[u][1]=x]=0;
        update(u);
        u=fa[x=u];
    }
}
inline void change(int x,int c){
    acc(x);
    key[x]=c;
    update(x);
}
inline void lca(int &u,int &v){
    acc(v);v=0;
    while(u){
        splay(u);
        if (!fa[u]) break;
        rt[ch[u][1]]=1;
        rt[ch[u][1]=v]=0;
        update(u);
        u=fa[v=u];
    }
}
inline int qu(int x,int y){
    lca(x,y);
    return max(ma[y],ma[ch[x][1]]);
}
inline void in(int x,int y,int c,int nu){
    num++;
    if (!l[x]) l[x]=num;else b[r[x]].ne=num;
    b[num].y=y;b[num].c=c;b[num].ne=0;b[num].nu=nu;r[x]=num;
}
inline void dfs(int x){
    for (int i=l[x];i;i=b[i].ne)
    if (!fa[b[i].y]){
        fa[b[i].y]=x;
        id[b[i].nu]=b[i].y;
        key[b[i].y]=b[i].c;
        dfs(b[i].y);
    }
}
char ss[10];
int main(){
    t=read();
    ma[0]=-1e9;
    while(t--){
        num=0;
        memset(rt,1,sizeof(rt));
        memset(fa,0,sizeof(fa));
        memset(ch,0,sizeof(ch));
        memset(l,0,sizeof(l));
        n=read();
        for (int i=1;i<n;i++){
            x=read();y=read();c=read();
            in(x,y,c,i);
            in(y,x,c,i);
        }
        fa[1]=-1;
        dfs(1);
        fa[1]=0;
        for(;;){
            scanf("%s",ss);
            if (ss[0]==‘D‘) break;
            x=read();y=read();
            if (ss[0]==‘Q‘) printf("%d\n",qu(x,y));else
            change(id[x],y);
        }
    }
}

				
时间: 2024-10-13 00:42:44

SPOJ QTREE - Query on a tree的相关文章

SPOJ QTREE Query on a tree ——树链剖分 线段树

[题目分析] 垃圾vjudge又挂了. 树链剖分裸题. 垃圾spoj,交了好几次,基本没改动却过了. [代码](自带常数,是别人的2倍左右) #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 20005 int T,n,fr[maxn],h[maxn],to[maxn],ne[maxn]

SPOJ QTREE Query on a tree --树链剖分

题意:给一棵树,每次更新某条边或者查询u->v路径上的边权最大值. 解法:做过上一题,这题就没太大问题了,以终点的标号作为边的标号,因为dfs只能给点分配位置,而一棵树每条树边的终点只有一个. 询问的时候,在从u找到v的过程中顺便查询到此为止的最大值即可. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath&

SPOJ - QTREE Query on a tree题解

题目大意: 一棵树,有边权,有两个操作:1.修改一条边的权值:2.询问两点间路径上的边的权值的最大值. 思路: 十分裸的树链剖分+线段树,无非是边权要放到深度大的一端的点上,但是有两个坑爹的地方,改了好久: 1.数组定义10000和40000会TLE,要乘10: 2.以前的树剖求解的最后是这样的: if (deep[x]>deep[y]) swap(x,y); return max(ans,MAX(1,n,id[x],id[y],1)); 但是WA了,膜拜大神后发现这样就AC了: if (x==

SPOJ QTREE Query on a Tree【树链剖分模板题】

树链剖分,线段树维护~ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> using namespace std; const int MAXN = 10014; struct Edge { int to,next; }edge[MAXN*2]; int head[MAXN],tot; int top[MA

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

SP375 QTREE - Query on a tree (树剖)

题目 SP375 QTREE - Query on a tree 解析 也就是个蓝题,因为比较长 树剖裸题(基本上),单点修改,链上查询. 可以看到这个题然我们对边进行操作,我们的树剖是对节点进行操作的,所以我们考虑把边权转移到点权上. 发现我们节点的点权是连向它的边的边权,所以我们要修改或查询边权的话,我们修改或查询的实际上是其连向点的点权, 假设我们要修改1-4之间的这两条边 我们修改的实际上就是这两个点 所以我们链上修改或查询的时候,不要修改或查询深度较浅的节点. 然后这是SPOJ上的题,

spoj 375. Query on a tree 【树链剖分--插点问线 】

题目:spoj 375. Query on a tree 题意:题意很清晰,就是给你一颗树,每两点之间有权值,然后改变一些权值,问一条路径上的最大值. 分析:入门题目,直接套树链模板 AC代码: #include <cstdio> #include <algorithm> #include <iostream> #include <string.h> using namespace std; const int N = 10010; #define Del(

SP375 QTREE - Query on a tree

SP375 QTREE - Query on a tree 我是借这道题来说说如何从c++改到c的 1.我怕麻烦,所以把结构体拆了(忍痛割爱我封装的线段树) 2.max.swap函数进行了手写 max: ll llmax(ll x,ll y){return x>y?x:y;} swap: x^=y^=x^=y emm...这的确是一个神奇的swap,不用函数 至于为什么是对的用人类智慧法即可 c++代码:(线段树封装) #include<bits/stdc++.h> using name

SPOJ 375. Query on a tree (树链剖分)

Query on a tree Time Limit: 5000ms Memory Limit: 262144KB This problem will be judged on SPOJ. Original ID: QTREE64-bit integer IO format: %lld      Java class name: Main Prev Submit Status Statistics Discuss Next Font Size: + - Type:   None Graph Th