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\) ...
随机推荐
- 用Flask+Redis维护Cookies池
Redis数据库:存储微博账号密码 这里需要购买账号 登录后的cookies:键值对的形式保存 GitHub:https://github.com/LXL-YAN/CookiesPool 视频讲解:h ...
- c++入门之引用
引用通常被用在函数形参传递的过程中.一般的参数传递的过程:将实参进行拷贝,函数中都是对拷贝的变量进行操作,而不是对原变量进行操作.但很多情况下,我们都希望对原变量进行操作.(比如交换两个变量的数值). ...
- JAVA项目中的常用的异常处理情况
NO.1 java.lang.NullPointerException 这个异常比较容易遇到,此异常的解释是“程序遇上了空指针”,简单地说就是调用了未经初始化的对象或者是不存在的对象,这个错误经常出现 ...
- kubectl常用命令汇总
#查看k8s的所有node节点 kubectl get node #查看ns的pod kubectl get pod --all-namespaces -o wide kubectl get pod ...
- Windows10 Build 18298 桌面显示计算机(此电脑)
- PHP中对象是按值传递还是按引用传递?
1.首先,什么是按值传递和按引用传递? 按值传递就是仅仅把值传递过去,相当于传递的是值的拷贝,而按引用传递传递的是内存的地址. 在 PHP5 中,如果按引用传递,就是将 zval 的地址赋给另一个变量 ...
- 902. Kth Smallest Element in a BST
Given a binary search tree, write a function kthSmallest to find the kth smallest element in it. You ...
- C# Note18: 使用wpf制作about dialog(关于对话框)
前言 基本上任何software或application都会在help菜单中,有着一个关于对话框,介绍产品的版权.版本等信息,还有就是对第三方的引用(add author credits). 首先,看 ...
- 进程有一个全局变量i,还有有两个线程。i++在两个线程里边分别执行100次,能得到的最大值和最小值分别是多少?
转自https://blog.csdn.net/biubiu741/article/details/77990592 i++不是原子操作,也就是说,它不是单独一条指令,而是3条指令: 1.从内存中把i ...
- Python深入类和对象
一. 鸭子类型和多态 1.什么是鸭子类型: 在程序设计中,鸭子类型(英语:Duck typing)是动态类型和某些静态语言的一种对象推断风格."鸭子类型"像多态一样工作,但是没有继 ...