zoukankan      html  css  js  c++  java
  • 【BZOJ】【2631】Tree

    LCT

      又一道名字叫做Tree的题目……

      看到删边加边什么的……又是动态树问题……果断再次搬出LCT。

      这题比起上道【3282】tree的难点在于需要像线段树维护区间那样,进行树上路径的权值修改&查询。那么类似的,我们就可以在splay的每个节点上记录一坨信息了……

    个人感觉跟线段树标记不一样的地方:

      1.标记只是给儿子们用的,打标记的节点本身在打标记的同时就修改了信息了,然后在Push_down的时候直接放下去……(没法在push_down的时候更新自己,要不mul标记怎么改?)

      2.虽然splay是按深度为关键字排序的,但是我们对整条路径操作的时候只要把一个端点上打了标记并且修改了就行了……(当然这个节点必须是“树根”)不用在意顺序……反正都加了就对了= =

    虽然不是很明白为什么这样打标记就是对的,在更改树的样子的时候也不会变……但是隐隐地感觉这样是可行的,而且也对了= =就这样姑且记下来好了

    另外,学习了另外一位大神的LCT模板,好像会快一些……?

      1 /**************************************************************
      2     Problem: 2631
      3     User: Tunix
      4     Language: C++
      5     Result: Accepted
      6     Time:14720 ms
      7     Memory:5724 kb
      8 ****************************************************************/
      9  
     10 //BZOJ 2631
     11 #include<cstdio>
     12 #include<cstring>
     13 #include<cstdlib>
     14 #include<iostream>
     15 #include<algorithm>
     16 #define rep(i,n) for(int i=0;i<n;++i)
     17 #define F(i,j,n) for(int i=j;i<=n;++i)
     18 #define D(i,j,n) for(int i=j;i>=n;--i)
     19 using namespace std;
     20 const int N=100086,MOD=51061;
     21 //#define debug
     22 void read(int &v){
     23     v=0;
     24     int sign=1; char ch=getchar();
     25     while(ch<'0' || ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
     26     while(ch>='0' && ch<='9'){v=v*10+ch-'0'; ch=getchar();}
     27     v*=sign;
     28 }
     29 //template of link-cut-tree for NOI2014 magic foreast
     30  
     31 int fa[N],c[N][2],size[N],n,m;
     32 unsigned int val[N],mul[N],add[N],sum[N];
     33 bool rev[N];
     34 #define L c[x][0]
     35 #define R c[x][1]
     36 /*
     37 void Push_up(int x){
     38     mid[x]=val[mid[c[x][0]]]>val[mid[c[x][1]]] ? mid[c[x][0]] : mid[c[x][1]] ,
     39     val[mid[x]]< val[x] ? mid[x]=x : 1;
     40 }
     41 */
     42 void Push_up(int x){
     43     sum[x]=val[x]; size[x]=1;
     44     L ? sum[x]=(sum[x]+sum[L]) % MOD,
     45         size[x]+=size[L] : 1;
     46     R ? sum[x]=(sum[x]+sum[R]) % MOD,
     47         size[x]+=size[R] : 1;
     48 }
     49 inline void update(int x,int mu,int ad){
     50     val[x]=(val[x]*mu+ad) % MOD;
     51     sum[x]=(sum[x]*mu+ad*size[x]) %MOD;
     52     mul[x]=(mul[x]*mu) % MOD;
     53     add[x]=(add[x]*mu+ad) % MOD;
     54 }
     55 int swap_tmp=0;
     56 void Push_down(int x){
     57     rev[x] ? rev[x]=0,rev[L]^=1,rev[R]^=1,swap_tmp=L,L=R,R=swap_tmp : 1;
     58     if(mul[x]!=1 || add[x]!=0) update(L,mul[x],add[x]),update(R,mul[x],add[x]),mul[x]=1,add[x]=0 ;
     59 }
     60 bool not_root(int x){
     61     return c[fa[x]][0]==x || c[fa[x]][1]==x;
     62 }
     63 void rotate(int x){
     64     int y=fa[x],p=c[y][1]==x;
     65     fa[x]=fa[y], not_root(y) ? c[fa[y]][ c[fa[y]][1]==y ]=x:1,
     66     (c[y][p]=c[x][!p]) ? fa[c[y][p]]=y : 1,
     67     Push_up(c[ fa[y]=x ][!p]=y);
     68 }
     69 void preview(int x){
     70     if (not_root(x)) preview(fa[x]);
     71     Push_down(x);
     72 }//从根到x全部Push_down一遍
     73 void splay(int x,int y=0){
     74     for(preview(x);not_root(x);rotate(x))
     75         not_root(y=fa[x]) ? rotate( (c[y][1]==x^c[fa[y]][1]==y ? x : y)),1 : 1;
     76     Push_up(x);
     77 }
     78 void access(int x,int las=0){
     79     for(;x;splay(x),c[x][1]=las,las=x,x=fa[x]);
     80 }
     81 void makeroot(int x){
     82     access(x),splay(x),rev[x]^=1;
     83 }
     84 int find(int x){
     85     access(x),splay(x);
     86     while(c[x][0]) x=c[x][0];
     87     return x;
     88 }
     89 void link(int x,int y){
     90     makeroot(x),fa[x]=y;
     91 }
     92 void cut(int x,int y){
     93     makeroot(x),access(y),splay(y);
     94     if (c[y][0]==x) c[y][0]=fa[x]=0;
     95 }
     96 void update_add(int x,int y,int v){
     97     makeroot(x),access(y),splay(y),add[y]=(add[y]+v)%MOD,val[y]=(val[y]+v)%MOD;
     98 }
     99 void update_mul(int x,int y,int v){
    100     makeroot(x),access(y),splay(y),mul[y]=(mul[y]*v)%MOD,val[y]=(val[y]*v)%MOD,add[y]=add[y]*v%MOD;
    101 }
    102 void query(int x,int y){
    103     makeroot(x),access(y),splay(y);
    104     printf("%d
    ",sum[y]);
    105 }
    106 /*
    107 int query(int x,int y){
    108     return makeroot(x),access(y),splay(y),mid[y];
    109 }
    110 */
    111 int main(){
    112     #ifndef ONLINE_JUDGE
    113     freopen("input.txt","r",stdin);
    114     #endif
    115     read(n); read(m);
    116     F(i,1,n) add[i]=0,val[i]=mul[i]=sum[i]=size[i]=1;
    117     int x,y,v;
    118     F(i,2,n){
    119         read(x); read(y);
    120         link(x,y);
    121     }
    122     char cmd[5];
    123     F(i,1,m){
    124         scanf("%s",cmd);
    125         read(x),read(y);
    126         switch(cmd[0]){
    127             case '+': read(v),update_add(x,y,v);break;
    128             case '-': cut(x,y); read(x),read(y); link(x,y);break;
    129             case '*': read(v),update_mul(x,y,v); break;
    130             case '/': query(x,y);break;
    131         }
    132         #ifdef debug
    133         printf("i=%d
    ",i);
    134         F(x,1,n) printf("%d %d %d %d %d %d %d
    ",fa[x],L,R,sum[x],val[x],mul[x],add[x]);
    135         #endif
    136     }
    137     return 0;
    138 }
    View Code
  • 相关阅读:
    MyBatis学习记录02篇
    Mybatis学习记录01篇
    项目路径问题
    项目01-JavaWeb网上书城01之工具类
    面试篇01
    创建多线程的方式
    关于web.xml
    快捷键----快速生成未实现的方法
    自动化学习-Day03
    自动化学习-Day02
  • 原文地址:https://www.cnblogs.com/Tunix/p/4224098.html
Copyright © 2011-2022 走看看