hihocoder#1333 : 平衡树·Splay2 (区间操作)
题面:
#1333 : 平衡树·Splay2
描述
小Ho:好麻烦啊~~~~~
小Hi:小Ho你在干嘛呢?
小Ho:我在干活啊!前几天老师让我帮忙管理一下团队的人员,但是感觉好难啊。
小Hi:说来听听?
小Ho:事情是这样的。我们有一个运动同好会,每天都有人加入或者退出,所以老师让我帮忙管理一下人员。每个成员有一个互不相同的id和他对我们同好会的兴趣值val,每隔一段时间一些成员的兴趣值就会发生变化。老师有时候也会问我一些成员的兴趣值。
小Hi:所以你就需要一个表格来管理信息咯?
小Ho:是啊,但是我们同好会的成员实在是太多了!我感觉完全搞不定啊。
小Hi:这样啊,那不如让我来帮帮你吧!
小Ho:真的吗?
小Hi:当然是真的啦,小Ho,你先告诉我有多少种需要完成的事情?
小Ho:一共有4种情况:
1. 加入:一个新的成员加入同好会,我会分配给他一个没有使用的id,并且询问他的兴趣值val。
2. 修改:id在区间[a,b]内的成员,兴趣值同时改变k,k有可能是负数,表示他们失去了对同好会的兴趣。
3. 退出:id在区间[a,b]内的成员要退出同好会,虽说是区间,也有可能只有1个人。
4. 询问:老师会问我在区间[a,b]内的成员总的兴趣值。
小Hi:我明白了,让我想一想该如何解决。
输入
第1行:1个正整数n,表示操作数量,100≤n≤200,000
第2..n+1行:可能包含下面4种规则:
1个字母'I',紧接着2个数字id,val,表示一个编号为id的新成员加入,其兴趣值为val,1≤id≤100,000,000,1≤val≤10,000,000,保证在团队中的每个人id都不相同。
1个字母'Q',紧接着2个数字a,b。表示询问团队中id在区间[a,b]的所有成员总兴趣值,保证区间内至少有一个成员,结果有可能超过int的范围。
1个字母'M',紧接着3个数字a,b,d,表示将团队中id在区间[a,b]的成员兴趣值都改变d,其中d有可能为负数。保证操作之后每个成员的兴趣值仍然在0~10,000,000。
1个字母'D',紧接着2个数字a,b,表示将团队中id在区间[a,b]的成员除去。
注意有可能出现一个id为1的成员加入团队,被除去之后,又有一个新的id为1的成员加入团队的情况。
输出
若干行:每行1个整数,表示针对询问的回答,保证一定有合法的解
- 样例输入
-
9
I 1 1
I 2 2
I 3 3
Q 1 3
M 1 2 2
Q 1 3
D 2 3
I 4 2
Q 1 4 - 样例输出
-
6
10
5 链接:http://hihocoder.com/problemset/problem/1333 代码:#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll M = 2e5+;
const ll inf = 0x3f3f3f;
ll n,sz,rt,t1,t2;
ll c[M][],sum[M],fa[M],id[M],tag[M],v[M],siz[M];
inline void pushup(ll k){
ll l = c[k][],r = c[k][];
sum[k] = sum[l] + sum[r] + v[k];
siz[k] = siz[l] + siz[r] + ;
} void pushdown(ll k){
ll l = c[k][],r = c[k][],t = tag[k];
if(t){
tag[k] = ;
if(l) tag[l]+=t,sum[l]+=t*siz[l],v[l]+=t;
if(r) tag[r]+=t,sum[r]+=t*siz[r],v[r]+=t;
}
} void rotate(ll x,ll &k){
ll y = fa[x],z = fa[y],l,r;
if(c[y][] == x) l = ;
else l = ;
r = l^;
if(y == k) k = x;
else {
if(c[z][]==y) c[z][]=x;
else c[z][] = x;
}
fa[x] = z;fa[y] = x;fa[c[x][r]]=y;
c[y][l]=c[x][r]; c[x][r]=y;
pushup(y); pushup(x);
} void splay(ll x,ll &k){
while(x != k){
ll y = fa[x],z = fa[y];
if(y != k){
if(c[y][]==x^c[z][]==y)rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
} inline void ask_befor(ll k,ll x){
pushdown(k);
if(k == ) return ;
if(id[k] <= x) {
t1 = k;
ask_befor(c[k][],x);
}
else ask_befor(c[k][],x);
} inline void ask_after(ll k,ll x){
pushdown(k);
if(k == ) return ;
if(id[k] >= x) {
t2 = k;
ask_after(c[k][],x);
}
else ask_after(c[k][],x);
} inline void ins(ll &k,ll idx,ll val,ll last){
pushdown(k);
if(k == ){
++sz;
siz[sz] = ;
k = sz;
v[k] = val;
sum[k] = val;
fa[k] = last;
id[k] = idx;
return ;
}
if(idx < id[k]) ins(c[k][],idx,val,k);
else ins(c[k][],idx,val,k);
pushup(k);
} inline void update(ll l,ll r,ll val){
ask_befor(rt,l-);ask_after(rt,r+);
ll x = t1,y = t2;
splay(x,rt); splay(y,c[x][]);
ll z = c[y][];
tag[z] += val;v[z] += val; sum[z] += val*siz[z];
} void del(ll l,ll r){
ask_befor(rt,l-);ask_after(rt,r+);
ll x = t1,y = t2;
splay(x,rt); splay(y,c[x][]);
c[y][] = ;
} inline void query(ll l,ll r){
ask_befor(rt,l-);ask_after(rt,r+);
ll x = t1,y = t2;
splay(x,rt); splay(y,c[x][]);
ll z = c[y][];
printf("%lld\n",sum[z]);
} int main()
{
sz = ;
ins(rt,-,,);
ins(rt,,,rt);
scanf("%lld",&n);
for(ll i = ;i <= n;i ++){
ll l,r,val;
string s;
cin>>s;
//cout<<s[0]<<endl;
scanf("%lld%lld",&l,&r);
if(s[] == 'M') scanf("%lld",&val),update(l,r,val);
else if(s[] == 'I') ins(rt,l,r,rt),splay(sz,rt);
else if(s[] == 'Q') query(l,r);
else del(l,r);
}
return ;
}
hihocoder#1333 : 平衡树·Splay2 (区间操作)的更多相关文章
- Hihocoder #1333 : 平衡树·Splay2
1333 : 平衡树·Splay2 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho:好麻烦啊~ 小Hi:小Ho你在干嘛呢? 小Ho:我在干活啊!前几天老师让我帮忙 ...
- hihocoder #1333 : 平衡树·Splay2
描述 小Ho:好麻烦啊~~~~~ 小Hi:小Ho你在干嘛呢? 小Ho:我在干活啊!前几天老师让我帮忙管理一下团队的人员,但是感觉好难啊. 小Hi:说来听听? 小Ho:事情是这样的.我们有一个运动同好会 ...
- Hihocoder 1329 平衡树·Splay(平衡树)
Hihocoder 1329 平衡树·Splay(平衡树) Description 小Ho:小Hi,上一次你跟我讲了Treap,我也实现了.但是我遇到了一个关键的问题. 小Hi:怎么了? 小Ho:小H ...
- Hihocoder 1333 (splay)
Problem 平衡树 splay2 题目大意 维护一个序列,支持四种操作: 操作1:添加一个数,编号为x,权值为y. 操作2:删除编号在区间[x,y]内的数. 操作3:将编号在区间[x,y]内的数的 ...
- Hihocoder 1325 平衡树·Treap(平衡树,Treap)
Hihocoder 1325 平衡树·Treap(平衡树,Treap) Description 小Ho:小Hi,我发现我们以前讲过的两个数据结构特别相似. 小Hi:你说的是哪两个啊? 小Ho:就是二叉 ...
- HihoCoder 1325 平衡树·Treap
HihoCoder 1325 平衡树·Treap 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho:小Hi,我发现我们以前讲过的两个数据结构特别相似. 小Hi:你说 ...
- Splay 的区间操作
学完Splay的查找作用,发现和普通的二叉查找树没什么区别,只是用了splay操作节省了时间开支. 而Splay序列之王的称号可不是白给的. Splay真正强大的地方是他的区间操作. 怎么实现呢? 我 ...
- POJ 3225 Help with Intervals --线段树区间操作
题意:给你一些区间操作,让你输出最后得出的区间. 解法:区间操作的经典题,借鉴了网上的倍增算法,每次将区间乘以2,然后根据区间开闭情况做微调,这样可以有效处理开闭区间问题. 线段树维护两个值: cov ...
- P2042 [NOI2005]维护数列 && Splay区间操作(四)
到这里 \(A\) 了这题, \(Splay\) 就能算入好门了吧. 今天是个特殊的日子, \(NOI\) 出成绩, 大佬 \(Cu\) 不敢相信这一切这么快, 一下子机房就只剩我和 \(zrs\) ...
随机推荐
- OO最后一次作业
终于开始最后一次作业了,是时候为这学期oo画一个圆满的局句号了. 回首这学期的OO经历,一路走来,经过了开始对面向对象的初步接触,然后就是充满痛苦回忆的多线程,接下来到了令人焦头烂额的规格设计,最后是 ...
- Node 系列之path模块
//引用该模块 var path = require("path"); 1.路径解析,得到规范化的路径格式 //对window系统,目录分隔为'\', 对于UNIX系统,分隔符为' ...
- Day8 Python基础之遗漏知识点(六)
1. 遗漏知识点 深.浅拷贝: http://www.cnblogs.com/yuanchenqi/articles/5782764.html a=b: 浅拷贝: 深拷贝 集合(set) 集合的定 ...
- NSAssert和NSParameterAssert
2016.05.05 18:34* 字数 861 阅读 5127评论 0喜欢 17 https://www.jianshu.com/p/3072e174554f NSAssert和NSParamete ...
- 线程中的samaphore信号量及event事件
一.信号量 samaphore: 在程序中意思为同时允许几个线程运行,比如我们去水上乐园的滑梯玩时,有四个滑梯,每一个滑梯上当没有人在中间玩滑下去时才允许上人,四个滑梯1,2,3,4,同时最多四个人, ...
- 单列模式,装饰器、new方法、类/静态方法实现单列模式
一.单列模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在. 如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 C ...
- remote:error:refusing to update checked out branc
参考网上的GIt服务器配置流程(http://blog.csdn.net/ice520301/article/details/6142503) 遇到了 http://www.cnblogs.com/c ...
- Python_迭代器、生成器、列表推导式,生成器表达式
1.迭代器 (1)可迭代对象 s1 = ' for i in s1: print(i) 可迭代对象 示例结果: D:\Python36\python.exe "E:/Python/课堂视频/ ...
- C# Note18: 使用wpf制作about dialog(关于对话框)
前言 基本上任何software或application都会在help菜单中,有着一个关于对话框,介绍产品的版权.版本等信息,还有就是对第三方的引用(add author credits). 首先,看 ...
- C++中String类的字符串分割实现
最近笔试,经常遇到需要对字符串进行快速分割的情景,主要是在处理输入的时候,而以前练习算法题或笔试,很多时候不用花啥时间考虑测试用例输入的问题.可是C++标准库里面没有像java的String类中提供的 ...