LCT spoj 375 树链剖分

来源:互联网 发布:洛阳seo牛广 编辑:程序博客网 时间:2024/05/08 05:18

树链剖分


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

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

心得


先推荐大家去看   点击打开链接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
原创粉丝点击