【题目链接】:http://hihocoder.com/problemset/problem/1333

【题意】

【题解】



伸展树;

要求提供操作:

1.插入一个元素,两个权值,id作为查找的比较权值,val作为储存信息;

2.将id在[a..b]范围内的点的val值改变d;d能为负值

3.将id在[a..b]范围内的点全部删掉;

4.查询id在[a..b]范围内的点的val值的和;

区间的更改要用到懒惰标记;

权值和,则需要在node域里面加一个变量,存当前子树的val和;

在旋转,插入,删除的时候,要更新权值和,同时下传懒惰标记.



【Number Of WA】



14(懒惰标记往下传的时候,乘错了,应该是乘子树的大小的)



【完整代码】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ms(x,y) memset(x,y,sizeof x) typedef pair<int,int> pii;
typedef pair<LL,LL> pll; const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
const int N = 110; struct node
{
int id;
LL val,sumval,lazy_tag,siz;
node *par,*child[2];
node(int id,LL val): id(id),val(val),sumval(val),lazy_tag(0),siz(1),par(NULL){}
}; int n;
char s[3];
node *root; void up_data(node *v)//更新这个节点,更新它的大小和权值和
{
v->sumval = v->val,v->siz = 1;
rep1(i,0,1)
if (v->child[i]!=NULL)
{
node *y = v->child[i];
v->sumval+=y->sumval;
v->siz+=y->siz;
}
} void add_tag(node *x)//懒惰标记下传
{
if (x->lazy_tag==0) return;
rep1(i,0,1)
if (x->child[i]!=NULL)
{
node *v = x->child[i];
v->val+=x->lazy_tag;
v->sumval+=1LL*x->lazy_tag*v->siz;//注意乘的是儿子节点的子树大小
v->lazy_tag+=x->lazy_tag;
}
x->lazy_tag = 0;
} void rotate(node* const x, int c) {//注意懒惰标记的下传位置
node* const y = x->par;
add_tag(y),add_tag(x);
y->child[c ^ 1] = x->child[c];
if (x->child[c] != NULL) x->child[c]->par = y;
x->par = y->par;
if (y->par != NULL && y->par->child[0] == y) y->par->child[0] = x;
else if (y->par != NULL && y->par->child[1] == y) y->par->child[1] = x;
y->par = x;
x->child[c] = y;
up_data(y),up_data(x);
} inline bool _splay_parent(node *x, node* (&y), node* stop) {
return (y = x->par) != stop && (x == y->child[0] || x == y->child[1]);
} void splay(node* const x, node* const stop) {
for (node *y, *z; _splay_parent(x, y, stop); ) {
if (_splay_parent(y, z, stop)) {
const int c = y == z->child[0];
if (x == y->child[c]) rotate(x, c ^ 1), rotate(x, c);
else rotate(y, c), rotate(x, c);
} else {
rotate(x, x == y->child[0]);
break;
}
}
if (stop == NULL) root = x;
} node *cr(node *u,int id,int val)//返回插入的节点所在的位置,如果已经存在则返回那个节点
{
add_tag(u);
if (u->id==id) return u;
if (u->child[id>u->id]==NULL)
{
node *v = new node(id,val);
v->child[0] = v->child[1] = NULL;
v->par = u;
u->child[id>u->id] = v;
return v;
}
node *temp = cr(u->child[id>u->id],id,val);
up_data(u);
return temp;
} void cr(int id,int val)//插入某个节点
{
node *u = cr(root,id,val);
splay(u,NULL);
} node * cz(node *u,int id)//查找某个权值,不存在就返回空
{
if (u->id == id) return u;
if (u->child[id>u->id]==NULL) return NULL;
return cz(u->child[id>u->id],id);
} node *get_max(node * v)//获取子树最大的权值所在节点
{
if (v->child[1]==NULL)
return v;
return get_max(v->child[1]);
} node *get_min(node *v)//获取子树最小的权值所在节点
{
if (v->child[0]==NULL)
return v;
return get_min(v->child[0]);
} void sc(int l,int r)//删除[l..r]这个区间
{
cr(l,0),cr(r,0);//删除操作获取l..r的时候,是先找到l的前驱和r的后继,然后一起删掉 node * u = cz(root,l);
splay(u,NULL);
node *lu = get_max(u->child[0]); node * v = cz(root,r);
splay(v,NULL);
node *rv = get_min(v->child[1]); splay(lu,NULL);
splay(rv,lu);
rv->child[0] = NULL;
up_data(rv),up_data(lu);
} void gb(int a,int b,int c)//把区间[l..r]的值都改变c
{
node *u = cz(root,a-1),*v = cz(root,b+1);//同理插入一个a-1和一个b+1
bool ju1 = (u==NULL),ju2 = (v==NULL);
if (ju1) u = cr(root,a-1,0);
if (ju2) v = cr(root,b+1,0);
splay(u,NULL);
splay(v,u);
if (v->child[0]!=NULL)
{
node *y = v->child[0];
y->val+=c;
y->sumval+=1LL*y->siz*c;
y->lazy_tag+=c;
up_data(v),up_data(u);
}
if (ju1) sc(a-1,a-1);
if (ju2) sc(b+1,b+1);
} LL query(int a,int b)//询问区间[a..b]的权值和
{
node *u = cz(root,a-1),*v = cz(root,b+1);
bool ju1 = (u==NULL),ju2 = (v==NULL);//看看有没有a-1和b+1,如果有的话,就能方便获取[a..b]了
if (ju1) u = cr(root,a-1,0);//没有的话就自己插入一个
if (ju2) v = cr(root,b+1,0);
splay(u,NULL);
splay(v,u);
LL temp = v->child[0]->sumval;
if (ju1) sc(a-1,a-1);
if (ju2) sc(b+1,b+1);
return temp;
} int main()
{
ios::sync_with_stdio(false),cin.tie(0);//scanf,puts,printf not use
root = new node(-1,0);
root->child[0] = root->child[1] = NULL;
cr(21e8,0);
cin >> n;
rep1(i,1,n)
{
cin >> s;
if (s[0]=='I')
{
int id,val;
cin >> id >> val;
cr(id,val);
}
if (s[0]=='D')
{
int a,b;
cin >> a >> b;
sc(a,b);
}
if (s[0]=='M')
{
int a,b,c;
cin >> a >> b >> c;
gb(a,b,c);
}
if (s[0]=='Q')
{
int a,b;
cin >> a >> b;
cout << query(a,b) << endl;
} }
return 0;
}

【hihocoder 1333】平衡树·Splay2的更多相关文章

  1. hihocoder#1333 : 平衡树·Splay2 (区间操作)

    题面: #1333 : 平衡树·Splay2 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho:好麻烦啊~~~~~ 小Hi:小Ho你在干嘛呢? 小Ho:我在干活啊! ...

  2. Hihocoder #1333 : 平衡树·Splay2

    1333 : 平衡树·Splay2 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho:好麻烦啊~ 小Hi:小Ho你在干嘛呢? 小Ho:我在干活啊!前几天老师让我帮忙 ...

  3. hihocoder #1333 : 平衡树·Splay2

    描述 小Ho:好麻烦啊~~~~~ 小Hi:小Ho你在干嘛呢? 小Ho:我在干活啊!前几天老师让我帮忙管理一下团队的人员,但是感觉好难啊. 小Hi:说来听听? 小Ho:事情是这样的.我们有一个运动同好会 ...

  4. Hihocoder 1325 平衡树·Treap(平衡树,Treap)

    Hihocoder 1325 平衡树·Treap(平衡树,Treap) Description 小Ho:小Hi,我发现我们以前讲过的两个数据结构特别相似. 小Hi:你说的是哪两个啊? 小Ho:就是二叉 ...

  5. HihoCoder 1325 平衡树·Treap

    HihoCoder 1325 平衡树·Treap 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho:小Hi,我发现我们以前讲过的两个数据结构特别相似. 小Hi:你说 ...

  6. Hihocoder 1329 平衡树·Splay(平衡树)

    Hihocoder 1329 平衡树·Splay(平衡树) Description 小Ho:小Hi,上一次你跟我讲了Treap,我也实现了.但是我遇到了一个关键的问题. 小Hi:怎么了? 小Ho:小H ...

  7. Hihocoder 1333 (splay)

    Problem 平衡树 splay2 题目大意 维护一个序列,支持四种操作: 操作1:添加一个数,编号为x,权值为y. 操作2:删除编号在区间[x,y]内的数. 操作3:将编号在区间[x,y]内的数的 ...

  8. [模版]平衡树splay2

    题目描述 1. 加入:一个新的成员加入同好会,我会分配给他一个没有使用的id,并且询问他的兴趣值val. 2. 修改:id在区间[a,b]内的成员,兴趣值同时改变k,k有可能是负数,表示他们失去了对同 ...

  9. hihocoder #1034 : 毁灭者问题 平衡树(set)+线段树

    #1034 : 毁灭者问题 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在 Warcraft III 之冰封王座中,毁灭者是不死族打三本后期时的一个魔法飞行单位. 毁 ...

随机推荐

  1. CF 447A(DZY Loves Hash-简单判重)

    A. DZY Loves Hash time limit per test 1 second memory limit per test 256 megabytes input standard in ...

  2. Codeforces Round #281 (Div. 2) D. Vasya and Chess 博弈

    D. Vasya and Chess   Vasya decided to learn to play chess. Classic chess doesn't seem interesting to ...

  3. ACM Amman Collegiate Programming Contest(7.22随机组队娱乐赛)

    题目链接 https://vjudge.net/contest/240074#overview 只写一下自己做的几个题吧 /* D n^2的暴力dp怎么搞都可以的 这里先预处理 i到j的串时候合法 转 ...

  4. fixed和absolute

    fixed是相对于浏览器窗口固定 absolute是相对于整体网页固定.(整体网页包括所有的内容,包含右侧滑动条滑动所能看到的内容)

  5. bzoj1116 [POI2008]CLO——并查集找环

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1116 分析性质,只要有环,那么给环定一下向就满足了条件: 环上点的其他边可以指向外面,所以两 ...

  6. 从0开始学习BFC

    为什么需要BFC? <style> .red { background: red; } .blue { background: #1890ff; } .green { background ...

  7. tp3.2 复合查询or

    tp3.2 复合查询or $where['goods_name'] = array("like","%$q%");$where['goods_sn'] = ar ...

  8. SpringBoot + Redis:基本配置及使用

    注:本篇博客SpringBoot版本为2.1.5.RELEASE,SpringBoot1.0版本有些配置不适用 一.SpringBoot 配置Redis 1.1 pom 引入spring-boot-s ...

  9. D - Vanya and Fence

    Problem description Vanya and his friends are walking along the fence of height h and they do not wa ...

  10. Linux学习笔记--文件夹结构

    暂时先上一张图学习吧,先大致了解好,再进行深入的学习.