LCT spoj 375 树链剖分

树链剖分


才完全看懂树链剖分  我好弱啊  

同学们都已经烂熟于心了    然而我却。。。

心得


先推荐大家去看   点击打开链接http://blog.sina.com.cn/s/blog_6974c8b20100zc61.html


这个博客讲的特别的好


树链剖分 就是 两遍dfs   把这棵树的各种路都铺好  top  fa  son(重儿子  好势利。。) 等等的   

在第二遍dfs  中  还有一个是  w数组  (signaficant) 这个数组 用来记录x作为儿子连得是第几条边   (注意是作为儿子  !因为 作为父亲可能连了好几条边)


读入优化 写的学习了


最最重要的是  也是为什么这个写法比比的写法要短的原因 :  线段树


他缩减了线段树因为在这个题目里面  根本就用不到  正常的build   .l  .r  .val  都用不到   所以在第二遍dfs  的时候 都可以初始化好


上自己的代码

   

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <string.h>
using namespace std;
const int maxn = 10010;

int tr[maxn];
int zzz, n, z, root, a, b, c;
int d[maxn][3];
int head[maxn], dep[maxn], w[maxn], fa[maxn], top[maxn], son[maxn], siz[maxn];
char ch[10];
struct edge{
     int to,next;
}e[maxn*2];
int cnt;
void insert (int u, int v)
{
    e[++cnt].to=v;
    e[cnt].next = head[u];
    head[u]=cnt;
}

void dfs1(int x)
{
     siz[x]=1,son[x]=0;
     for(int i=head[x];i;i=e[i].next)
     {
          if(e[i].to!=fa[x])
          {
               fa[e[i].to]=x;
               dep[e[i].to]=dep[x]+1;
               dfs1(e[i].to);
               siz[x]+=siz[e[i].to];
               if(siz[e[i].to]>siz[son[x]])
                  son[x]=e[i].to;
          }
     }
}

void build_tree(int x,int tp)
{
     w[x]=++z;
     top[x]=tp;
     if(son[x])
        build_tree(son[x],top[x]);
     for(int i=head[x];i;i=e[i].next)
       {
            if(e[i].to!=son[x]&&e[i].to!=fa[x])
            {
                 build_tree(e[i].to,e[i].to);
            }
       }
}

void updata(int ro,int lt,int rt,int k,int val)
{
      if(k>rt||k<lt)
        return ;
       if(lt==rt)
         tr[ro]=val;
       else
       {
           int mid=(lt+rt)>>1;
           updata(ro<<1,lt,mid,k,val);
           updata(ro<<1|1,mid+1,rt,k,val);
           tr[ro]=max(tr[ro<<1],tr[ro<<1|1]);
       }
       
}

int q(int ro,int lt,int rt,int l,int r)
{
     if(l>rt||r<lt)
       return 0;
      if(r<=rt&&l>=lt) 
        return tr[ro];
      int mid=(lt+rt)>>1;
      return max(q(ro<<1,lt,mid,l,r),q(ro<<1|1,mid+1,rt,l,r));
      
}

inline int find(int a,int b)
{
     int f1=top[a],f2=top[b],temp=0;
     while(f1!=f2)
     {
          if(dep[f1]<dep[f2])
            swap(f1,f2),swap(a,b);
          temp=max(temp,q(1,1,z,w[f1],w[a]));
           a=fa[f1]; 
           f1=top[a];
     }
     if(a==b)
       return temp;
     if(dep[a]>dep[b])
      swap(a,b);
      return max(temp,q(1,1,z,w[son[a]],w[b]));
}

void init()
{
     scanf("%d",&n);
     root=(n+1)>>1;
     fa[root]=z=dep[root]=0;
     memset(head,0,sizeof(head));
     memset(tr,0,sizeof(tr));
     memset(siz,0,sizeof(siz));
     for(int i=1;i<n;i++)
     {
          scanf("%d%d%d",&a,&b,&c);
          d[i][0]=a;
          d[i][1]=b;
          d[i][2]=c;
          insert(a,b);
          insert(b,a);
     }
     dfs1(root);
     build_tree (root,root);
     for(int i=1;i<n;i++)
     {
         if(dep[d[i][0]]>dep[d[i][1]])
           swap(d[i][0],d[i][1]);
         updata(1,1,z,w[d[i][1]],d[i][2]);
     }
}

inline void rd()
{
   ch[0]=' ';
   while(ch[0]<'C'||ch[0]>'Q')
     scanf("%s",&ch);
}

void work()
{
     for(rd();ch[0]!='D';rd())
     {
          scanf("%d%d",&a,&b);
          if(ch[0]=='Q')
          {
              printf("%d",find(a,b));
          }
          else
          {
              updata(1,1,z,w[d[a][1]],b);
          }
     }
}

int main()
{
     for(scanf("%d",&zzz);zzz>0;zzz--)
     {
          init();
          work();
     }
     return 0;
}

写的很烂  毕竟我是弱弱


By LT 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值