• 【bzoj2631】tree link-cut-tree


    2016-06-01 08:50:36

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2631

    注意加和乘的标记下传问题。

    还有就是split后,要分清x和y哪个是祖先。

    pushup在access和rotate后都要进行。

    这题还卡常数,开ll就会T,开unsigned int即可。

      1 #include<bits/stdc++.h>
      2 #define inf 1000000000
      3 #define uint unsigned int
      4 #define N 100005
      5 #define mod 51061
      6 using namespace std;
      7 int read(){
      8   int x=0,f=1;char ch=getchar();
      9   while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     10   while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     11   return x*f;
     12 }
     13 int n,q;
     14 char ch[5];
     15 namespace LCT{
     16   int ch[N][2],fa[N],sz[N];bool rev[N];
     17   uint cj[N],add[N],val[N],sum[N];
     18   inline bool isroot(int x){
     19     if(ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x)return 1;return 0;
     20   }
     21   void change(int x,int c,int a){
     22     if(!x)return;
     23     val[x]=(val[x]*c+a)%mod;
     24     sum[x]=(sum[x]*c+a*sz[x])%mod;
     25     add[x]=(add[x]*c+a)%mod;
     26     cj[x]=(cj[x]*c)%mod;
     27   }
     28   void pushdown(int x){
     29     if(rev[x]){
     30       rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;rev[x]^=1;
     31       swap(ch[x][0],ch[x][1]);
     32     }
     33     if(cj[x]!=1||add[x]!=0){
     34       change(ch[x][0],cj[x],add[x]);
     35       change(ch[x][1],cj[x],add[x]);
     36     }
     37     cj[x]=1;add[x]=0;
     38   }
     39   void Pushdown(int x){
     40     if(!isroot(x))Pushdown(fa[x]);
     41     pushdown(x);
     42   }
     43   void pushup(int x){
     44     sum[x]=(sum[ch[x][0]]+sum[ch[x][1]]+val[x])%mod;
     45     sz[x]=(sz[ch[x][0]]+sz[ch[x][1]]+1)%mod;
     46   }
     47   void rotate(int x){
     48     int y=fa[x],k=ch[y][1]==x;
     49     if(!isroot(y))ch[fa[y]][ch[fa[y]][1]==y]=x;
     50     fa[x]=fa[y];
     51     fa[ch[x][!k]]=y;
     52     fa[y]=x;
     53     ch[y][k]=ch[x][!k];
     54     ch[x][!k]=y;
     55     pushup(y);pushup(x);
     56   }
     57   void splay(int x){
     58     Pushdown(x);
     59     for(int y=fa[x];!isroot(x);y=fa[x]){
     60       if(!isroot(y)){
     61         if((ch[fa[y]][ch[fa[y]][1]==y])!=(ch[y][1]==x))rotate(x);
     62         else rotate(y);
     63       }rotate(x);
     64     }
     65   }
     66   inline void access(int x){
     67     int y=0;
     68     while(x){
     69       splay(x);
     70       ch[x][1]=y;pushup(x);
     71       x=fa[y=x];
     72     }
     73   }
     74   inline void moveroot(int x){
     75     access(x);splay(x);rev[x]^=1;
     76   }
     77   inline void link(int x,int y){
     78     moveroot(x);fa[x]=y;splay(x);
     79   }
     80   inline void cut(int x,int y){
     81     moveroot(x);access(y);splay(y);ch[y][0]=fa[x]=0;
     82   }
     83   inline void split(int x,int y){
     84     moveroot(y);access(x);splay(x);
     85   }
     86 }
     87 int main(){
     88   n=read();q=read();
     89   for(int i=1;i<=n;i++)LCT::val[i]=LCT::sum[i]=LCT::cj[i]=LCT::sz[i]=1;
     90   for(int i=1;i<n;i++)LCT::link(read(),read());
     91   while(q--){
     92     scanf("%s",ch);
     93     int u=read(),v=read();
     94     if(ch[0]=='+')LCT::split(u,v),LCT::change(u,1,read());
     95     else if(ch[0]=='-'){
     96       LCT::cut(u,v);u=read();v=read();LCT::link(u,v);
     97     }
     98     else if(ch[0]=='*')LCT::split(u,v),LCT::change(u,read(),0);
     99     else LCT::split(u,v),printf("%d
    ",LCT::sum[u]%mod);
    100   }
    101   return 0;
    102 }
    View Code

    2631: tree

    Time Limit: 30 Sec  Memory Limit: 128 MB
    Submit: 3385  Solved: 1137
    [Submit][Status][Discuss]

    Description

     一棵n个点的树,每个点的初始权值为1。对于这棵树有q个操作,每个操作为以下四种操作之一:
    + u v c:将u到v的路径上的点的权值都加上自然数c;
    - u1 v1 u2 v2:将树中原有的边(u1,v1)删除,加入一条新边(u2,v2),保证操作完之后仍然是一棵树;
    * u v c:将u到v的路径上的点的权值都乘上自然数c;
    / u v:询问u到v的路径上的点的权值和,求出答案对于51061的余数。

     

    Input

      第一行两个整数n,q
    接下来n-1行每行两个正整数u,v,描述这棵树
    接下来q行,每行描述一个操作
     

    Output

      对于每个/对应的答案输出一行
     

    Sample Input

    3 2
    1 2
    2 3
    * 1 3 4
    / 1 1

    Sample Output

    4


    HINT

    数据规模和约定

    10%的数据保证,1<=n,q<=2000

    另外15%的数据保证,1<=n,q<=5*10^4,没有-操作,并且初始树为一条链

    另外35%的数据保证,1<=n,q<=5*10^4,没有-操作

    100%的数据保证,1<=n,q<=10^5,0<=c<=10^4

  • 相关阅读:
    【LeetCode】152. 乘积最大子数组(DP)
    【剑指Offer】49. 丑数(三指针)
    [P1979][NOIP2013] 华容道 (BFS建图+SPFA)
    [P1850][NOIP2016] 换教室 (期望+DP+Floyd)
    差分约束学习笔记
    [P1291][SHOI2002] 百事世界杯之旅 (期望)
    [P4342][IOI1998] Polygon (区间DP)
    [P3802] 小魔女帕琪 (期望)
    [P1273] 有线电视网 (树形DP+分组背包)
    树链剖分学习
  • 原文地址:https://www.cnblogs.com/wjyi/p/5548401.html
Copyright © 2020-2023  润新知