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 namespace std;
const int N=100005;
typedef long long ll;
struct line{
    int from,to;
    ll val;
    int conec;
}s[N];
int n;
int hed[N],tal[N<<1],nxt[N<<1],cnt=0;
ll val[N<<1];
int fa[N];
int dep[N];
int size[N]={0};
int son[N]={0};
int dfn[N];
int rk[N];
int indexy=0;
int top[N];
ll v[N];
ll llmax(ll x,ll y){return x>y?x:y;}
struct Sugment_Tree{
    ll t[N<<2];
    #define mid (l+r)/2
    void push_up(int num){
        t[num]=llmax(t[num<<1],t[num<<1|1]);
    }
    void build(int l,int r,int num){
        if(l==r){
            t[num]=v[l];
            return;
        }
        build(l,mid,num<<1),build(mid+1,r,num<<1|1);
        push_up(num);
    }
    void upd(int l,int r,int num,int pos,ll SUM){
        if(l>pos||r<pos) return;
        if(l==r&&r==pos){
            t[num]=SUM;
            return;
        }
        upd(l,mid,num<<1,pos,SUM);
        upd(mid+1,r,num<<1|1,pos,SUM);
        push_up(num);
    }
    ll ask(int l,int r,int num,int L,int R){
        if(l>R||r<L) return 0;
        if(l>=L&&r<=R) return t[num];
        return llmax(ask(l,mid,num<<1,L,R),ask(mid+1,r,num<<1|1,L,R));
    }
}T;
void addege(int x,int y,ll z){
    cnt++;
    tal[cnt]=y;
    val[cnt]=z;
    nxt[cnt]=hed[x];
    hed[x]=cnt;
}
void dfs1(int u,int pa){
    fa[u]=pa;
    size[u]=1;
    for(int i=hed[u];i;i=nxt[i]){
        int v=tal[i];
        if(v==fa[u]) continue;
        dep[v]=dep[u]+1;
        dfs1(v,u);
        size[u]+=size[v];
        if(size[v]>size[son[u]]) son[u]=v;
    }
}
void dfs2(int u,int tp){
    indexy++;
    dfn[u]=indexy;
    rk[dfn[u]]=u;
    top[u]=tp;
    if(!son[u]) return;
    dfs2(son[u],tp);
    for(int i=hed[u];i;i=nxt[i]){
        int v=tal[i];
        if(v==fa[u]||v==son[u]) continue;
        dfs2(v,v);
    }
}

ll cgn(int x,int y){
    ll ans=0;
    //LCA不能算进来!!!!!!
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        ans=llmax(ans,T.ask(1,n,1,dfn[top[x]],dfn[x]));
        x=fa[top[x]];
    }
    if(dep[x]<dep[y]) swap(x,y);
    ans=llmax(ans,T.ask(1,n,1,dfn[y]+1,dfn[x]));
    return ans;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        scanf("%d%d%lld",&s[i].from,&s[i].to,&s[i].val);
        addege(s[i].from,s[i].to,s[i].val);
        addege(s[i].to,s[i].from,s[i].val);
    }
    dep[1]=1;
    dfs1(1,1);
    dfs2(1,1);
    for(int i=1;i<n;i++){
        if(fa[s[i].from]==s[i].to) v[dfn[s[i].from]]=s[i].val,s[i].conec=dfn[s[i].from];
        else v[dfn[s[i].to]]=s[i].val,s[i].conec=dfn[s[i].to];
    }
    /*
    for(int i=1;i<=n;i++)
        cout<<v[i]<<" ";
    cout<<endl;
    */
    T.build(1,n,1);
    char c[10];
    while(1){
        scanf("%s",c);
        if(c[0]==‘D‘) break;
        else if(c[0]==‘Q‘){
            int x,y;
            scanf("%d%d",&x,&y);
            if(x==y){
                printf("0\n");
                continue;
            }
            printf("%lld\n",cgn(x,y));
        }
        else{
            int pos;
            ll va;
            scanf("%d%lld",&pos,&va);
            T.upd(1,n,1,s[pos].conec,va);
        }
    }
    return 0;
} 

c:

#include <ctype.h>
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#define N 100005
typedef long long ll;
int from_P[N];
int to_P[N];
ll val_P[N];
int conec_P[N];
int n;
int hed[N],tal[N<<1],nxt[N<<1],cnt=0;
ll val[N<<1];
int fa[N];
int dep[N];
int size[N]={0};
int son[N]={0};
int dfn[N];
int rk[N];
int indexy=0;
int top[N];
ll v[N];
int TE;
ll llmax(ll x,ll y){return x>y?x:y;}
    ll t[N<<2];
    #define mid (l+r)/2
    void push_up(int num)
    {
        t[num]=llmax(t[num<<1],t[num<<1|1]);
    }
    void build(int l,int r,int num)
    {
        if(l==r)
        {
            t[num]=v[l];
            return;
        }
        build(l,mid,num<<1),build(mid+1,r,num<<1|1);
        push_up(num);
    }
    void upd(int l,int r,int num,int pos,ll SUM)
    {
        if(l>pos||r<pos) return;
        if(l==r&&r==pos)
        {
            t[num]=SUM;
            return;
        }
        upd(l,mid,num<<1,pos,SUM);
        upd(mid+1,r,num<<1|1,pos,SUM);
        push_up(num);
    }
    ll ask(int l,int r,int num,int L,int R)
    {
        if(l>R||r<L) return 0;
        if(l>=L&&r<=R) return t[num];
        return llmax(ask(l,mid,num<<1,L,R),ask(mid+1,r,num<<1|1,L,R));
    }
void addege(int x,int y,ll z)
{
    cnt++;
    tal[cnt]=y;
    val[cnt]=z;
    nxt[cnt]=hed[x];
    hed[x]=cnt;
}
void dfs1(int u,int pa)
{
    fa[u]=pa;
    size[u]=1;
    for(int i=hed[u];i;i=nxt[i])
    {
        int v=tal[i];
        if(v==fa[u]) continue;
        dep[v]=dep[u]+1;
        dfs1(v,u);
        size[u]+=size[v];
        if(size[v]>size[son[u]]) son[u]=v;
    }
}
void dfs2(int u,int tp)
{
    indexy++;
    dfn[u]=indexy;
    rk[dfn[u]]=u;
    top[u]=tp;
    if(!son[u]) return;
    dfs2(son[u],tp);
    for(int i=hed[u];i;i=nxt[i])
    {
        int v=tal[i];
        if(v==fa[u]||v==son[u]) continue;
        dfs2(v,v);
    }
}

ll cgn(int x,int y)
{
    ll ans=0;
    //LCA不能算进来!!!!!!
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) x^=y^=x^=y;
        ans=llmax(ans,ask(1,n,1,dfn[top[x]],dfn[x]));
        x=fa[top[x]];
    }
    if(dep[x]<dep[y]) x^=y^=x^=y;
    ans=llmax(ans,ask(1,n,1,dfn[y]+1,dfn[x]));
    return ans;
}
int main()
{
    scanf("%d",&TE);
    while(TE--)
    {
        cnt=0;
        indexy=0;
        for(int i=0;i<N;i++) hed[i]=0;
        for(int i=0;i<N;i++) dep[i]=0;
        for(int i=0;i<N;i++) size[i]=0;
        for(int i=0;i<N;i++) son[i]=0;
        scanf("%d",&n);
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%lld",&from_P[i],&to_P[i],&val_P[i]);
            addege(from_P[i],to_P[i],val_P[i]);
            addege(to_P[i],from_P[i],val_P[i]);
        }
        dep[1]=1;
        dfs1(1,1);
        dfs2(1,1);
        for(int i=1;i<n;i++)
        {
            if(fa[from_P[i]]==to_P[i]) v[dfn[from_P[i]]]=val_P[i],conec_P[i]=dfn[from_P[i]];
            else v[dfn[to_P[i]]]=val_P[i],conec_P[i]=dfn[to_P[i]];
        }
        /*
        for(int i=1;i<=n;i++)
            cout<<v[i]<<" ";
        cout<<endl;
        */
        build(1,n,1);
        char c[10];
        while(1)
        {
            scanf("%s",c);
            if(c[0]==‘D‘) break;
            else if(c[0]==‘Q‘)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                if(x==y)
                {
                    printf("0\n");
                    continue;
                }
                printf("%lld\n",cgn(x,y));
            }
            else
            {
                int pos;
                ll va;
                scanf("%d%lld",&pos,&va);
                upd(1,n,1,conec_P[pos],va);
            }
        }
    }
    return 0;
} 

原文地址:https://www.cnblogs.com/QYJ060604/p/11623986.html

时间: 2024-11-11 16:44:00

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

SP375 QTREE - Query on a tree (树剖)

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

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】

\[ \texttt{Preface} \] 这题在 \(\text{Luogu}\) 上竟然不能交 \(C++\) ,会一直 \(Waiting\) ,只能交非 \(C++\) 的语言. 所以打完了 \(C++\) 要转到 \(C\) 才能过. 要把什么 \(swap\) , \(max\) 各种函数换成手写,以及 \(C++\) 的特色(例如 using namespace std; 和 inline )都要去掉. 详情见 \(Code\) . \[ \texttt{Description}

spoj375 QTREE - 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 tior QUERY a b : ask fo

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 tior QUERY

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

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

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

题目链接:http://www.spoj.com/problems/QTREE/en/ 题意:  一棵树 n 个节点,每条边上有权值,同时有两个操作: (1)更改操作:CHANGE i ti(把第 i 条边上的权值改为 ti). (2)查询操作:QUERY a b(查询 a 到 b 的路径上权值最大的边的权值). 思路(树链剖分): 看到这种区间查询的题想要用数据结构优化,提高时间效率一般会想到线段树.可是这次操作的对象并不是一组序列, 无法直接使用线段树.这时,我们可以做些转化:对树作树链剖分

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 375 QTREE - Query on a tree 树链剖分

题目链接 给一棵树, 每条边有权值, 两种操作, 一种是将一条边的权值改变, 一种是询问u到v路径上最大的边的权值. 树链剖分模板. #include <iostream> #include <vector> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <map> #include <set&g