嘟嘟嘟




这道题其实还是挺基础的,只不过操作有点多。




区间乘和区间加按线段树的方式想。

那么就先要下放乘标记,再下放加标记。但这两个和反转标记是没有先后顺序的。

对于区间加,sum加的是区间长度\(*\)lazy标记。但是线段树区间固定,而lct不是,所以还要单独维护一个size。

还有一点,这个是splay的性质,就是当前节点的sum还要算上自己的权值,而不像线段树完全由子树信息合并而来。

最最最后一点,得开long long,包括点权。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 1e5 + 5;
const ll mod = 51061;
inline ll read()
{
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) last = ch, ch = getchar();
while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
} int n, q;
char c[2];
struct Tree
{
int ch[2], fa;
int siz, rev;
ll val, sum, add, mul;
}t[maxn]; In void c_rev(int now)
{
swap(t[now].ch[0], t[now].ch[1]);
t[now].rev ^= 1;
}
In void c_mul(int now, ll lzy)
{
t[now].sum *= lzy; t[now].sum %= mod;
t[now].val *= lzy; t[now].val %= mod;
t[now].mul *= lzy; t[now].mul %= mod;
t[now].add *= lzy; t[now].add %= mod;
}
In void c_add(int now, ll lzy)
{
t[now].sum += lzy * (ll)t[now].siz; t[now].sum %= mod;
t[now].val += lzy; t[now].val %= mod;
t[now].add += lzy; t[now].add %= mod;
}
In void pushdown(int now)
{
if(t[now].rev)
{
if(t[now].ch[0]) c_rev(t[now].ch[0]);
if(t[now].ch[1]) c_rev(t[now].ch[1]);
t[now].rev = 0;
}
if(t[now].mul != 1)
{
if(t[now].ch[0]) c_mul(t[now].ch[0], t[now].mul);
if(t[now].ch[1]) c_mul(t[now].ch[1], t[now].mul);
t[now].mul = 1;
}
if(t[now].add)
{
if(t[now].ch[0]) c_add(t[now].ch[0], t[now].add);
if(t[now].ch[1]) c_add(t[now].ch[1], t[now].add);
t[now].add = 0;
}
}
In void pushup(int now)
{
t[now].siz = t[t[now].ch[0]].siz + t[t[now].ch[1]].siz + 1;
t[now].sum = (t[t[now].ch[0]].sum + t[t[now].ch[1]].sum + t[now].val) % mod;
}
In bool n_root(int now)
{
return t[t[now].fa].ch[0] == now || t[t[now].fa].ch[1] == now;
}
In void rotate(int x)
{
int y = t[x].fa, z = t[y].fa, k = (t[y].ch[1] == x);
if(n_root(y)) t[z].ch[t[z].ch[1] == y] = x; t[x].fa = z;
t[y].ch[k] = t[x].ch[k ^ 1]; t[t[y].ch[k]].fa = y;
t[x].ch[k ^ 1] = y; t[y].fa = x;
pushup(y), pushup(x);
}
int st[maxn], top = 0;
In void splay(int x)
{
int y = x;
st[top = 1] = y;
while(n_root(y)) st[++top] = y = t[y].fa;
while(top) pushdown(st[top--]);
while(n_root(x))
{
int y = t[x].fa, z = t[y].fa;
if(n_root(y)) rotate(((t[y].ch[0] == x) ^ (t[z].ch[0] == y)) ? x : y);
rotate(x);
}
}
In void access(int x)
{
int y = 0;
while(x)
{
splay(x); t[x].ch[1] = y;
pushup(x);
y = x; x = t[x].fa;
}
}
In void make_root(int x)
{
access(x); splay(x);
c_rev(x);
}
In int find_root(int x)
{
access(x); splay(x);
while(t[x].ch[0]) pushdown(x), x = t[x].ch[0];
return x;
}
In void split(int x, int y)
{
make_root(x);
access(y); splay(y);
}
In void Link(int x, int y)
{
make_root(x);
if(find_root(y) != x) t[x].fa = y;
}
In void Cut(int x, int y)
{
make_root(x);
if(find_root(y) == x && t[x].fa == y && !t[x].ch[1])
t[y].ch[0] = t[x].fa = 0, pushup(y);
} int main()
{
n = read(); q = read();
for(int i = 1; i <= n; ++i) t[i].val = t[i].mul = t[i].siz = 1;
for(int i = 1, x, y; i < n; ++i) x = read(), y = read(), Link(x, y);
for(int i = 1; i <= q; ++i)
{
scanf("%s", c); int x = read(), y = read();
if(c[0] == '+') {int d = read(); split(x, y); c_add(y, d);}
else if(c[0] == '*') {int d = read(); split(x, y); c_mul(y, d);}
else if(c[0] == '/') split(x, y), write(t[y].sum), enter;
else
{
Cut(x, y);
x = read(), y = read();
Link(x, y);
}
}
return 0;
}

[国家集训队]Tree II的更多相关文章

  1. P1501 [国家集训队]Tree II(LCT)

    P1501 [国家集训队]Tree II 看着维护吧2333333 操作和维护区间加.乘线段树挺像的 进行修改操作时不要忘记吧每个点的点权$v[i]$也处理掉 还有就是$51061^2=2607225 ...

  2. 洛谷 P1501 [国家集训队]Tree II 解题报告

    P1501 [国家集训队]Tree II 题目描述 一棵\(n\)个点的树,每个点的初始权值为\(1\).对于这棵树有\(q\)个操作,每个操作为以下四种操作之一: + u v c:将\(u\)到\( ...

  3. 【洛谷 P1501】 [国家集训队]Tree II(LCT)

    题目链接 Tree Ⅱ\(=\)[模板]LCT+[模板]线段树2.. 分别维护3个标记,乘的时候要把加法标记也乘上. 还有就是模数的平方刚好爆\(int\),所以开昂赛德\(int\)就可以了. 我把 ...

  4. 【洛谷1501】[国家集训队] Tree II(LCT维护懒惰标记)

    点此看题面 大致题意: 有一棵初始边权全为\(1\)的树,四种操作:将两点间路径边权都加上一个数,删一条边.加一条新边,将两点间路径边权都加上一个数,询问两点间路径权值和. 序列版 这道题有一个序列版 ...

  5. 洛谷P1501 [国家集训队]Tree II(LCT,Splay)

    洛谷题目传送门 关于LCT的其它问题可以参考一下我的LCT总结 一道LCT很好的练习放懒标记技巧的题目. 一开始看到又做加法又做乘法的时候我是有点mengbi的. 然后我想起了模板线段树2...... ...

  6. 洛谷.1501.[国家集训队]Tree II(LCT)

    题目链接 日常zz被define里没取模坑 //标记下放同线段树 注意51061^2 > 2147483647,要开unsigned int //*sz[]别忘了.. #include < ...

  7. 【刷题】洛谷 P1501 [国家集训队]Tree II

    题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原有的 ...

  8. 洛谷P1501 [国家集训队]Tree II(LCT)

    题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原有的 ...

  9. p1501 [国家集训队]Tree II

    传送门 分析 lct板子题 单独维护一下加和乘的情况即可 维护方法和维护翻转差不多 代码 #include<iostream> #include<cstdio> #includ ...

随机推荐

  1. eclipse中如何向开源中国(码云)上传代码

    摘要 本文将介绍如何将本地的项目提交到开源中国上去,过程比较详细,实现起来很简单.由于自己也算是一个新手,所以没有做过多的解释,只是单纯的描述了该如何去做.   1.在开源中国上面新建一个空项目 到这 ...

  2. springboot自定义banner生成器

    http://patorjk.com/software/taag/#p=display&f=Graffiti&t=Type%20Something%20

  3. VirtualBox配置centos7静态ip(详解)

    VirtualBox安装centos7配置静态ip地址可以本机访问,可以联网. 在开始之前先说一下,不知道为什么,我在网上百度的大多数是不能用的,或者只能主机访问,或者只能联网. 我的配置文件为ifc ...

  4. Idea无法运行Maven项目

    导入项目到tomcat的时候要选择Arifact 如果maven项目没有这个选项, <groupId>com.bihang</groupId> <artifactId&g ...

  5. POJ3616(KB12-R dp)

    Milking Time Time Limit: 1000MS    Memory Limit: 65536K Total Submissions: 9459  Accepted: 3935   De ...

  6. git中的ssh和https方式的使用(gitee为例)

    在使用git管理代码,或者使用github,国内的码云(gitee)的时候,有两种方式可以使用,分别是https和ssh,以下均使用gitee为例. ssh方式 配置ssh,如果不配置ssh的话,cl ...

  7. 08:Vigenère密码

    08:Vigenère密码 查看 提交 统计 提问 总时间限制:  1000ms 内存限制:  65536kB 描述 16世纪法国外交家Blaise de Vigenère设计了一种多表密码加密算法— ...

  8. VC工程从Win32环境往Win64环境迁移的经验总结

    作者:朱金灿 来源:http://blog.csdn.net/clever101 首先需要安装Win64的开发环境,具体参考: VS 2008的64位编译环境的安装和使用 其次在工程属性设置中作如下修 ...

  9. .net中反射与IOC容器实现

    反射还是很有用的,比如IOC容器基本上都是通过反射实现的. IOC是什么 IOC:Inversion of Control 控制反转是一种是面向对象编程中的一种设计原则,用来减低计算机代码之间的耦合度 ...

  10. [Android] (在ScrollView里嵌套view)重叠view里面的onTouchEvent的调用方法

    在我前面的自定义裁剪窗口的代码中,我把裁剪的view放在了大的scrollview里,这样就出现了程序只能触发scrollview,无法操作我的裁剪窗口.所以我加了那篇博客下面最后两段代码.其实我遇到 ...