• P1501 [国家集训队]Tree II


    题目描述

    一棵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的余数。

    输入输出格式

    输入格式:

    第一行两个整数n,q

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

    接下来q行,每行描述一个操作

    输出格式:

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

    输入输出样例

    输入样例#1:
    3 2
    1 2
    2 3
    * 1 3 4
    / 1 1
    输出样例#1:
    4
    

    说明

    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

    题解

    一起膜拜flashhu大佬%%%

    不知道为什么我的LCT板子好像各种有问题……和大佬的各种操作兼容不起来……然后也不知道要怎么改……

    总之就是在树上打上各种标记,然后向线段树一样记得下传……

    然后各种细节我一个都没考虑到……多亏了大佬的提醒orz

     1 //minamoto
     2 #include<bits/stdc++.h>
     3 #define int unsigned int
     4 #define mod 51061
     5 using namespace std;
     6 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
     7 char buf[1<<21],*p1=buf,*p2=buf;
     8 inline int read(){
     9     #define num ch-'0'
    10     char ch;bool flag=0;int res;
    11     while(!isdigit(ch=getc()))
    12     (ch=='-')&&(flag=true);
    13     for(res=num;isdigit(ch=getc());res=res*10+num);
    14     (flag)&&(res=-res);
    15     #undef num
    16     return res;
    17 }
    18 const int N=100005;
    19 int n,fa[N],ch[N][2],v[N],sum[N],sz[N],tmul[N],tadd[N],s[N],top,rev[N];
    20 bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
    21 void pushup(int x){
    22     sum[x]=(sum[ch[x][0]]+sum[ch[x][1]]+v[x])%mod;
    23     sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
    24 }
    25 void pushrev(int x){
    26     swap(ch[x][0],ch[x][1]);rev[x]^=1;
    27 }
    28 #define mul(x) x*=c,x%=mod
    29 #define add(x,c) x+=c,x%=mod
    30 void pushmul(int x,int c){
    31     mul(sum[x]),mul(v[x]),mul(tmul[x]),mul(tadd[x]);
    32 }
    33 void pushadd(int x,int c){
    34     add(sum[x],c*sz[x]),add(v[x],c),add(tadd[x],c);
    35 }
    36 #undef mul
    37 #undef add
    38 void pushdown(int x){
    39     if(tmul[x]!=1) pushmul(ch[x][0],tmul[x]),pushmul(ch[x][1],tmul[x]),tmul[x]=1;
    40     if(tadd[x]) pushadd(ch[x][0],tadd[x]),pushadd(ch[x][1],tadd[x]),tadd[x]=0;
    41     if(rev[x]) {if(ch[x][0]) pushrev(ch[x][0]);if(ch[x][1]) pushrev(ch[x][1]);rev[x]=0;}
    42 }
    43 void rotate(int x){
    44     int y=fa[x],z=fa[y],d=(ch[y][1]==x);if(!isroot(y)) ch[z][ch[z][1]==y]=x;
    45     fa[x]=z,fa[y]=x;fa[ch[x][d^1]]=y,ch[y][d]=ch[x][d^1],ch[x][d^1]=y;pushup(y),pushup(x);
    46 }
    47 void splay(int x){
    48     s[top=1]=x;for(int i=x;!isroot(i);i=fa[i]) s[++top]=fa[i];for(int i=top;i>=1;--i) pushdown(s[i]);
    49     for(int y=fa[x],z=fa[y];!isroot(x);y=fa[x],z=fa[y]){
    50         if(!isroot(y)) ((ch[z][1]==y)^(ch[y][1]==x))?rotate(x):rotate(y);rotate(x);
    51     }
    52 }
    53 void access(int x){int t=0;while(x){splay(x),ch[x][1]=t,pushup(x),t=x,x=fa[x];}}
    54 void makeroot(int x){access(x),splay(x),pushrev(x);}
    55 int findroot(int x){access(x);splay(x);pushdown(x);while(ch[x][0]) pushdown(x=ch[x][0]);return x;}
    56 void split(int x,int y){makeroot(x),access(y),splay(y);}
    57 void link(int x,int y){makeroot(x),fa[x]=y;}
    58 void cut(int x,int y){split(x,y),fa[x]=ch[y][0]=0;}
    59 #undef int
    60 int main(){
    61     //freopen("testdata.in","r",stdin);
    62     int n,q;
    63     n=read(),q=read();
    64     for(int i=1;i<=n;++i) tmul[i]=sz[i]=v[i]=1;
    65     for(int i=1;i<n;++i){
    66         int u=read(),v=read();
    67         link(u,v);
    68     }
    69     while(q--){
    70         char ch;
    71         while((ch=getc())<'*');
    72         switch(ch){
    73             case '+':{
    74                 int a=read(),b=read(),k=read();
    75                 split(a,b),pushadd(b,k);
    76                 break;
    77             }
    78             case '-':{
    79                 int a=read(),b=read();cut(a,b);
    80                 a=read(),b=read(),link(a,b);
    81                 break;
    82             }
    83             case '*':{
    84                 int a=read(),b=read(),k=read();
    85                 split(a,b),pushmul(b,k);
    86                 break;
    87             }
    88             case '/':{
    89                 int a=read(),b=read();
    90                 split(a,b);
    91                 printf("%d
    ",sum[b]);
    92                 break;
    93             }
    94         }
    95     }
    96 }
  • 相关阅读:
    c#遍历文件夹获得所有文件
    var的一些理解
    Pycharm使用秘籍
    RESTful规范
    Django文档阅读-Day4
    Django文档阅读-Day3
    Django文档阅读-Day2
    Django文档阅读-Day1
    你的博客园奇丑无比怎么办?
    基于scrapy框架输入关键字爬取有关贴吧帖子
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9413622.html
Copyright © 2020-2023  润新知