Spoj375 Qtree--树链剖分

Posted cutemush

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spoj375 Qtree--树链剖分相关的知识,希望对你有一定的参考价值。

Spoj375 Qtree
给一棵共有 n(n · 10000) 个结点的树, 每条边都有一个权值, 要求维护一个数据结构, 支持如下操作:
1. 修改某条边的权值;
2. 询问某两个结点之间的唯一通路上的最大边权.
其中操作的总次数为 q.
Sample Input
3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE
Sample Output
1
3

 

#include<cstdio>
#include<algorithm>
#include<cstring> 
using namespace std;
int sum,maxx,n,m,f[30001],pre[100001],nxt[100001],h[30001],now,size[100001],dep[100001],id[30001],top[30001],cnt,y[30001],z[30001],x[30001];
struct oo
{
	int a,b,mx;
}
s[100001];
char p[9];
void dfs(int x)
{
    size[x]=1;
    for(int i=h[x];i;i=nxt[i])
    {
        if(pre[i]==f[x])
		   continue;
        dep[pre[i]]=dep[x]+1;
        f[pre[i]]=x;
        dfs(pre[i]);
        size[x]+=size[pre[i]];
    }
}
void dfs2(int x,int f)
{
    int k=0;
    id[x]=++cnt;//x在线段树中的位置 
    top[x]=f;//标记top结记 
    for(int i=h[x];i;i=nxt[i]) // 找出重儿子 
        if(size[pre[i]]>size[k]&&dep[pre[i]]>dep[x])
		   k=pre[i];
    if(!k)
	    return ;
    dfs2(k,f);
    for(int i=h[x];i;i=nxt[i])
        if(dep[pre[i]]>dep[x]&&pre[i]!=k)
            dfs2(pre[i],pre[i]);
}
void ins(int x,int y)
{
    pre[++now]=y;
    nxt[now]=h[x];
    h[x]=now;
}
void build(int x,int l,int r)
{
    s[x].a=l;
	s[x].b=r;
    if(l==r)
	 {
			s[x].mx=-1e9;
			return ;
	 }
    build(x<<1,l,l+r>>1);
    build(x<<1|1,(l+r>>1)+1,r);
    s[x].mx=max(s[x<<1].mx,s[x<<1|1].mx);
}
void get(int x,int l,int r)
{
    if(s[x].a>=l&&r>=s[x].b)
        maxx=max(s[x].mx,maxx);
    else
    {
        int mid=s[x].a+s[x].b>>1;
        if(l<=mid)
		    get(x<<1,l,r);
        if(r>mid)
		    get(x<<1|1,l,r);
    }
}
void qmax(int x,int y)
{
    maxx=-1e9;
    while(top[x]!=top[y])//当没有在一条重链上时 
    {
        if(dep[top[x]]<dep[top[y]])
		   swap(x,y);
        get(1,id[top[x]],id[x]);
        x=f[top[x]];
    }
    if(id[x]>id[y])
	    swap(x,y);
    get(1,id[x]+1,id[y]);
}
void change(int x,int l,int v)
{
    if(s[x].a==s[x].b)
    {
        s[x].mx=v;
        return ;
    }
    int mid=s[x].a+s[x].b>>1;
    if(l<=mid)
	    change(x<<1,l,v);
    else 
	    change(x<<1|1,l,v);
    s[x].mx=max(s[x<<1].mx,s[x<<1|1].mx);
}
int T;
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        memset(h,0,sizeof h);
        now=0;cnt=0;
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%d",&x[i],&y[i],&z[i]);
            ins(x[i],y[i]);
			ins(y[i],x[i]);
        }
        dfs(1);
		dfs2(1,1); 
        build(1,1,n);
        for(int i=1;i<n;i++)
        {
            int a=id[x[i]],b=id[y[i]];
            if(dep[x[i]]>dep[y[i]])
            //将边权放到点上,要放到这条边的儿子点上
			//因为某个点可以会有多个子结点,放父亲点,就会出问题了 
			   change(1,a,z[i]),z[i]=a;//记下第i条边在线段树中的位置 
			 
            else 
			   change(1,b,z[i]),z[i]=b;
        }
        while(1)
        {
            int a,b;
            scanf("%s",p+1);
            if(p[1]==‘Q‘)
            {
                scanf("%d%d",&a,&b);
                qmax(a,b);
                printf("%d
",maxx);
            } 
            if(p[1]==‘D‘)break;
            if(p[1]==‘C‘)
                scanf("%d%d",&a,&b),change(1,z[a],b);
        }
    }
}

  

以上是关于Spoj375 Qtree--树链剖分的主要内容,如果未能解决你的问题,请参考以下文章

SPOJ QTREE 树链剖分

SPOJ 375 QTREE

[SPOJ375]QTREE

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

学术篇SPOJ QTREE 树链剖分

SPOJ - QTREE(树链剖分+单点更新+区间最大值查询)