BZOJ2631 tree(伍一鸣) LCT 秘制标记

这个题一看就是裸地LCT嘛,但是我wa了好几遍,这秘制标记......

注意事项:I.*对+有贡献 II.先下传*再下传+(因为我们已经维护了+,不能再让*对+产生贡献)III.维护+用到size

#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 100005
#define P 51061
using namespace std;
inline unsigned int read()
{
    unsigned int sum=0;
    char ch=getchar();
    while(ch<‘0‘||ch>‘9‘)ch=getchar();
    while(ch>=‘0‘&&ch<=‘9‘)
    {
       sum=(sum<<1)+(sum<<3)+ch-‘0‘;
       ch=getchar();
    }
    return sum;
}
struct LCT
{
    struct Node
    {
        Node *ch[2],*f;
        unsigned int key,multi,pluss,sum,size;
        bool rev;
        void pushup()
        {
            sum=(key+ch[0]->sum+ch[1]->sum)%P;
            size=ch[0]->size+1+ch[1]->size;
        }
    }null[MAXN];
    void swap(Node *&x,Node *&y)
    {
        Node *temp=x;
        x=y;
        y=temp;
    }
    void pushdown(Node *p)
    {
        if(p->rev)
        {
            p->ch[0]->rev^=1;
            p->ch[1]->rev^=1;
            swap(p->ch[0],p->ch[1]);
            p->rev=0;
        }
        if(p->multi!=1)
        {
            p->ch[0]->sum=(p->ch[0]->sum*p->multi)%P;
            p->ch[0]->key=(p->ch[0]->key*p->multi)%P;
            p->ch[0]->pluss=(p->ch[0]->pluss*p->multi)%P;
            p->ch[0]->multi=(p->ch[0]->multi*p->multi)%P;
            p->ch[1]->sum=(p->ch[1]->sum*p->multi)%P;
            p->ch[1]->key=(p->ch[1]->key*p->multi)%P;
            p->ch[1]->pluss=(p->ch[1]->pluss*p->multi)%P;
            p->ch[1]->multi=(p->ch[1]->multi*p->multi)%P;
            p->multi=1;
        }
        if(p->pluss)
        {
            if(p->ch[1]!=null)
            {
               p->ch[1]->sum=(p->ch[1]->sum+p->pluss*p->ch[1]->size)%P;
               p->ch[1]->key=(p->ch[1]->key+p->pluss)%P;
               p->ch[1]->pluss=(p->ch[1]->pluss+p->pluss)%P;
            }
            if(p->ch[0]!=null)
            {
               p->ch[0]->sum=(p->ch[0]->sum+p->pluss*p->ch[0]->size)%P;
               p->ch[0]->key=(p->ch[0]->key+p->pluss)%P;
               p->ch[0]->pluss=(p->ch[0]->pluss+p->pluss)%P;
            }
            p->pluss=0;
        }
    }
    void Init()
    {
       null->ch[1]=null->ch[0]=null->f=null;
       for(unsigned int i=1;i<MAXN;i++)
        null[i].ch[0]=null[i].ch[1]=null[i].f=null,null[i].sum=null[i].key=null[i].multi=1,null[i].pluss=0;
    }
    bool isroot(Node *p)
    {
       return p->f->ch[0]!=p&&p->f->ch[1]!=p;
    }
    unsigned int get(Node *p)
    {
       return p->f->ch[1]==p;
    }
    void rotate(Node *p)
    {
       Node *fa=p->f,*pa=fa->f;
       unsigned int j=get(p);
       if(!isroot(fa))pa->ch[get(fa)]=p;
       if((fa->ch[j]=p->ch[j^1])!=null)fa->ch[j]->f=fa;
       fa->f=p;
       p->f=pa;
       p->ch[j^1]=fa;
       fa->pushup();
       p->pushup();
    }
    void spaly(Node *p)
    {
        pushdown(p);
        for(Node *fa=p->f;!isroot(p);rotate(p),fa=p->f)
        if(!isroot(fa))
        {
            pushdown(fa->f),pushdown(fa),pushdown(p);
            rotate(get(fa)==get(p)?fa:p);
        }
        else
            pushdown(fa),pushdown(p);
    }
    void expose(Node *x)
    {
        Node *y=null;
        while(x!=null)
        {
           spaly(x);
           x->ch[1]=y;
           x->pushup();
           y=x;
           x=x->f;
        }
    }
    void make_root(Node *p)
    {
        expose(p);
        spaly(p);
        p->rev^=1;
    }
    void cut(unsigned int a,unsigned int b)
    {
        Node *x=null+a,*y=null+b;
        make_root(x);
        expose(y);
        spaly(y);
        y->ch[0]->f=null;
        y->ch[0]=null;
        y->pushup();
    }
    void link(unsigned int a,unsigned int b)
    {
        Node *x=null+a,*y=null+b;
        make_root(x);
        x->f=y;
    }
    void up(unsigned int a,unsigned int b,unsigned int c)
    {
        Node *x=null+a,*y=null+b;
        make_root(x);
        expose(y);
        spaly(y);
        y->pluss=(y->pluss+c)%P;
        y->key=(y->key+c)%P;
        y->sum=(y->sum+y->size*c)%P;
    }
    void UUP(unsigned int a,unsigned int b,unsigned int c)
    {
        Node *x=null+a,*y=null+b;
        make_root(x);
        expose(y);
        spaly(y);
        y->multi=(y->multi*c)%P;
        y->key=(y->key*c)%P;
        y->sum=(y->sum*c)%P;
        y->pluss=(y->pluss*c)%P;
    }
    unsigned int query(unsigned int a,unsigned int b)
    {
        Node *x=null+a,*y=null+b;
        make_root(x);
        expose(y);
        spaly(y);
        return y->sum;
    }
}YY;
int main()
{
    YY.Init();
    unsigned int n=read(),m=read();
    for(unsigned int i=1;i<n;i++)
    {
       unsigned int x=read(),y=read();
       YY.link(x,y);
    }
    for(unsigned int i=1,x,y,z,a,b;i<=m;i++)
    {
       char ch;
       cin>>ch;
       x=read(),y=read();
       switch(ch)
       {
           case ‘*‘:z=read();
                    YY.UUP(x,y,z);
                    break;
           case ‘+‘:z=read();
                    YY.up(x,y,z);
                    break;
           case ‘-‘:a=read(),b=read();
                    YY.cut(x,y);
                    YY.link(a,b);
                    break;
           case ‘/‘:printf("%d\n",YY.query(x,y));
                    break;
       }
    }
    return 0;
}
时间: 2024-10-13 12:34:51

BZOJ2631 tree(伍一鸣) LCT 秘制标记的相关文章

Tsinsen A1303. tree(伍一鸣) LCT

LCT的各种操作.... cut link add mul size rev query 写的效率不够高...BZOJ上似乎TLE.... A1303. tree(伍一鸣) 时间限制:2.5s   内存限制:64.0MB 总提交次数:727   AC次数:238   平均分:45.59 将本题分享到: 查看未格式化的试题   提交   试题讨论 试题来源 2012中国国家集训队命题答辩 问题描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v

[COGS 1799][国家集训队2012]tree(伍一鸣)

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,

【国家集训队2012】tree(伍一鸣)

题面 传送门 Sol 这不是一道LCT模板题吗? 和线段树一样维护区间加法和乘法标记 记得要更新自己本身的权值 这种题就该一遍AC # include <bits/stdc++.h> # define RG register # define IL inline # define Fill(a, b) memset(a, b, sizeof(a)) # define Sqr(x) ((x) * (x)) # define ls ch[0][x] # define rs ch[1][x] usi

秘制牛肉团队博客目录

秘制牛肉团队博客目录 一.Scrum Meeting 1. Alpha 团队第一次 # scrum meeting 团队第二次 # scrum meeting 团队第三次 # scrum meeting 团队第四次 # scrum meeting 团队第五次 # scrum meeting 团队第六次 # scrum meeting 团队第七次 # scrum meeting 团队第八次 # scrum meeting 团队第九次 # scrum meeting 团队第十次 # scrum me

老八秘制小汉堡

先来成品图: package 老八汉堡; import java.awt.*; import javax.swing.*; public class Window extends JPanel { JFrame frame; static JButton but[][] = new JButton[2][6]; private String str[][] = { { "臭豆腐", "俘虏", "老干妈", "美汁汁儿", &

[线段树系列] LCT打延迟标记的正确姿势

这一篇博客将教你什么? 如何用LCT打延迟标记,LCT和线段树延迟标记间的关系,为什么延迟标记要这样打. ——正片开始—— 学习这一篇博客前,确保你会以下知识: Link-Cut-Tree,普通线段树 当然,不会也没有关系,你可以先收藏这篇博客,等你学了以后再来看. 最好通过了这一道题:[模板]线段树Ⅱ 没有通过也没关系,对于本篇的知识只是一个启发作用. 我们平时使用的Link-Cut-Tree一般只需要打一个翻转标记rev[x]. 然后我们用pushR(x)函数来下发翻转标记. 那么我们现在来

《Head First Servlets & JSP》-10-定制标记开发

标记文件:很想include,但是比include更好 建立和使用标记文件的最简方法 取一个被包含文件(如Header.jsp),把它重命名为带有一个.tag扩展名(Header.tag): 把标记文件(Header.tag)放在WEB-INF目录下一个名为tags的目录中: 在JSP中放一个taglib指令(有一个tagdir属性),并调用这个标记: 如何向标记文件发送参数? 对于标记文件,发送的不是请求参数,而是标记属性! 在JSP中调用标记: 在标记文件中使用属性: 如何定义标记文件中所需

bzoj2631: tree lct

要打mul和add的lct 50000+的mod用unsigned int好了TAT (坑爹没打pc('\n');(静态)调了好久,样例竟然只输出一个,orz,也不提示PE T_T) 1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<cstdio> 6 7 using namespace std; 8 9 co

HDU 5002 Tree(动态树LCT)(2014 ACM/ICPC Asia Regional Anshan Online)

Problem Description You are given a tree with N nodes which are numbered by integers 1..N. Each node is associated with an integer as the weight. Your task is to deal with M operations of 4 types: 1.Delete an edge (x, y) from the tree, and then add a