P4114 Qtree1

P4114 Qtree1

题解

树链剖分的恶心题目

1.读入边,连边存边

2.两遍DFS

   第一遍找出每个点的重儿子 son  fa  size

   第二遍更新 dfn  dep  top 

3.把边权放到深度较大的结点上

4.线段树建树存边

5.线段树单点修改,区间查询

6.树链剖分查询的时候,一开始a,b路径可能是一个v形,然后不断跳跃重链,直到他们在一条重链上,然后两点中深度大的在下面,询问该区间的最大值

 

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<cstdlib>
#include<queue>

using namespace std;

inline int read()
{
    int ans=0;
    char last=' ',ch=getchar();
    while(ch<'0'||ch>'9') last=ch,ch=getchar();
    while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar();
    if(last=='-') ans=-ans;
    return ans;
}

const int maxn=1e5+10;
const int maxm=2e5+10;
int n,cnt=0;
struct nod
{
    int u,v,w;
}edge[maxm];
int head[maxn],to[maxm],nxt[maxm];
inline void addedge(int u,int v)
{
    to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;
    to[++cnt]=u;nxt[cnt]=head[v];head[v]=cnt;
}

int tim=0;
int size[maxn],son[maxn],dfn[maxn],top[maxn],dep[maxn],fa[maxn];

void dfs1(int u,int f)
{
    fa[u]=f;
    son[u]=0;
    size[u]=1;
    for(int i=head[u],v;i;i=nxt[i])
    {
        if(v=to[i] ,v!=f)
        {
            dfs1(v,u);
            size[u]+=size[v];
            if(size[v]>size[son[u]]) son[u]=v;
        }
    }
}
void dfs2(int u,int f)
{
    tim++;
    dfn[u]=tim;
    dep[u]=dep[f]+1;
    top[u]= (u==son[f] ? top[f] : u);
    if(son[u]!=0) dfs2(son[u],u);
    for(int i=head[u],v;i;i=nxt[i])
    {
        if(v=to[i],v!=f&&v!=son[u])
          dfs2(v,u);
    }
}

int val[maxn];

int zd[maxn<<2];

void modify(int k,int l,int r,int p,int v)
{
    if(l==r) { zd[k]=v;return; }
    else
    {
        int mid=(l+r)>>1;
        if(p<=mid) modify(k<<1,l,mid,p,v);
        else modify(k<<1|1,mid+1,r,p,v);
        zd[k]=max(zd[k<<1],zd[k<<1|1]);
    }
}

int  query(int k,int l,int r,int x,int y)
{
    if(x>y||y<l||x>r) return 0;
    if(x<=l&&r<=y) return zd[k];
    else
    {
        int mid=(l+r)>>1;
        return max(query(k<<1,l,mid,x,y),
                   query(k<<1|1,mid+1,r,x,y));
    }
}

int query(int a,int b)
{
    int ans=0;
    int ta=top[a],tb=top[b];
    while(ta!=tb)
    {
        if(dep[ta]>dep[tb])
          ans=max(ans,query(1,1,n,dfn[ta],dfn[a])),ta=top[a=fa[ta]];
        else 
          ans=max(ans,query(1,1,n,dfn[tb],dfn[b])),tb=top[b=fa[tb]];
    }
    if(dep[a]>dep[b]) swap(a,b);
    return max(ans,query(1,1,n,dfn[a]+1,dfn[b]));
}

int main()
{
    n=read();
    for(int i=1;i<n;i++)
    {
        edge[i].u =read();
        edge[i].v =read();
        edge[i].w =read();
        addedge(edge[i].u ,edge[i].v );
    }    
    dfs1(1,0);
    dfs2(1,0);
    for(int i=1;i<n;i++)
    {
        if(dep[edge[i].u] >dep[edge[i].v ]) 
           swap(edge[i].u ,edge[i].v );
        val[edge[i].v ]=edge[i].w ;
    }
    for(int i=1;i<=n;i++)
      modify(1,1,n,dfn[i],val[i]); 
    char s[10];
    while(scanf("%s",s),s[0]!='D')
    {
        int a,b;
        a=read();b=read();
        if(s[0]=='Q') printf("%d\n",query(a,b));
        if(s[0]=='C') modify(1,1,n,dfn[edge[a].v ],b);
    }

    return 0;
}

 

posted @ 2019-08-10 22:11  晔子  阅读(161)  评论(0编辑  收藏  举报