POJ 3468.A Simple Problem with Integers 解题报告
用树状数组和线段树会比较简单,这里用这道题来学习Splay。
第一次写,代码比较丑
/*
初始化添加一个key值足够大的结点
保证每个需要的结点都有后继
*/
#include <iostream>
#include <cstdio>
#define ll long long
using namespace std; const int MAXN = , INF = 0x7fffffff; struct node {
//需要的记录信息
ll key, val, sum, lazy, Size, Cnt;
//指向儿子和父亲的指针
node *ch[], *pre;
node() {pre = ch[] = ch [] = ; Size = ; key = ;}
node (ll key) : key (key) {pre = ch[] = ch[] = ; Size = , Cnt = , lazy = ;}
void Csize() {
Size = Cnt;
if (ch[] != NULL) Size += ch[]->Size;
if (ch[] != NULL) Size += ch[]->Size;
}
void Csum() {
sum = val;
if (ch[] != NULL) sum += ch[]->sum + ch[]->Size * ch[]->lazy;
if (ch[] != NULL) sum += ch[]->sum + ch[]->Size * ch[]->lazy;
}
} nil (), *NIL = &nil; struct Splay {
node *root, nod[MAXN];
int ncnt;//计算key值不同的结点数,已去重
Splay() {
ncnt = ;
root = & (nod[ncnt++] = node (INF) );
root->pre = NIL;
root->val = root->sum = ;
}
void Push_Down (node *x) {
if (x->lazy != ) {
if (x->ch[] != NULL) x->ch[]->lazy += x->lazy;
if (x->ch[] != NULL) x->ch[]->lazy += x->lazy;
x->val+=x->lazy;
}
x->lazy = ;
} void Update (node *x) {
x->Csize();
x->Csum();
} void Rotate (node *x, int sta) { //单旋转操作,0左旋,1右旋
node *p = x->pre, *g = p->pre;
Push_Down (p), Push_Down (x);
p->ch[!sta] = x->ch[sta];
if (x->ch[sta] != NULL) x->ch[sta]->pre = p;
x->pre = g;
if (g != NIL)
if (g->ch[] == p) g->ch[] = x;
else g->ch[] = x;
x->ch[sta] = p, p->pre = x, Update (p);
if (p == root ) root = x;
} void splay (node *x, node *y) { //Splay 操作,表示把结点x,转到根
for (Push_Down (x) ; x->pre != y;) { //将x的标记往下传
if (x->pre->pre == y) { //目标结点为父结点
if (x->pre->ch[] == x) Rotate (x, );
else Rotate (x, );
}
else {
node *p = x->pre, *g = p->pre;
if (g->ch[] == p)
if (p->ch[] == x)
Rotate (p, ), Rotate (x, );// / 一字型双旋转
else
Rotate (x, ), Rotate (x, );// < 之字形双旋转 else if (p ->ch[] == x)
Rotate (p, ), Rotate (x, );// \ 一字型旋转
else
Rotate (x, ), Rotate (x, ); // >之字形旋转
}
}
Update (x); //维护x结点
}
//找到中序便利的第K个结点,并旋转至结点y的下面。
void Select (int k, node *y) {
int tem ;
node *t ;
for ( t = root; ; ) {
Push_Down (t) ; //标记下传
tem = t->ch[]->Size ;
if (k == tem + ) break ; //找到了第k个结点 t
if (k <= tem)
t = t->ch[] ; //第k个结点在左子树
else
k -= tem + , t = t->ch[] ;//在右子树
}
splay (t, y);
}
bool Search (ll key, node *y) {
node *t = root;
for (; t != NULL;) {
Push_Down (t);
if (t->key > key && t->ch[] != NULL) t = t->ch[];
else if (t->key < key && t->ch[] != NULL) t = t->ch[];
else
break;
}
splay (t, y);
return t->key == key;
}
void Insert (int key, int val) {
if (Search (key, NIL) ) root->Cnt++, root->Size++;
else {
int d = key > root->key;
node *t = & (nod[++ncnt] = node (key) );
Push_Down (root);
t->val = t->sum = val;
t->ch[d] = root->ch[d];
if (root->ch[d] != NULL) root->ch[d]->pre = t;
t->ch[!d] = root;
t->pre = root->pre;
root->pre = t;
root->ch[d] = NULL;
Update (root);
root = t;
}
Update (root);
}
} sp; ll n, m, x;
int main() {
scanf ("%lld %lld", &n, &m);
sp.Insert (, );
sp.Insert (n + , );
for (int i = ; i <= n; i++) {
scanf ("%lld", &x);
sp.Insert (i, x);
}
char cmd;
int l, r;
for (int i = ; i <= m; i++) {
scanf ("\n%c %d %d", &cmd, &l, &r);
sp.Search (l - , NIL);
sp.Search (r + , sp.root);
if (cmd == 'Q') {
node *t = sp.root->ch[]->ch[];
ll ans = t->sum + t->Size * t->lazy;
printf ("%lld\n", ans);
}
if (cmd == 'C') {
ll c;
scanf ("%lld", &c);
sp.root->ch[]->ch[]->lazy += c;
}
}
return ;
}
POJ 3468.A Simple Problem with Integers 解题报告的更多相关文章
- POJ.3468 A Simple Problem with Integers(线段树 区间更新 区间查询)
POJ.3468 A Simple Problem with Integers(线段树 区间更新 区间查询) 题意分析 注意一下懒惰标记,数据部分和更新时的数字都要是long long ,别的没什么大 ...
- poj 3468 A Simple Problem with Integers 【线段树-成段更新】
题目:id=3468" target="_blank">poj 3468 A Simple Problem with Integers 题意:给出n个数.两种操作 ...
- 线段树(成段更新) POJ 3468 A Simple Problem with Integers
题目传送门 /* 线段树-成段更新:裸题,成段增减,区间求和 注意:开long long:) */ #include <cstdio> #include <iostream> ...
- poj 3468 A Simple Problem with Integers(线段树+区间更新+区间求和)
题目链接:id=3468http://">http://poj.org/problem? id=3468 A Simple Problem with Integers Time Lim ...
- POJ 3468 A Simple Problem with Integers(分块入门)
题目链接:http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS Memory Limit ...
- POJ 3468 A Simple Problem with Integers(线段树功能:区间加减区间求和)
题目链接:http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS Memory Limit ...
- [ACM] poj 3468 A Simple Problem with Integers(段树,为段更新,懒惰的标志)
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 55273 ...
- poj 3468 A Simple Problem with Integers 线段树区间加,区间查询和
A Simple Problem with Integers Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://poj.org/problem?i ...
- poj 3468 A Simple Problem with Integers 线段树区间加,区间查询和(模板)
A Simple Problem with Integers Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://poj.org/problem?i ...
随机推荐
- 51单片机的堆栈指针(SP)
堆栈指针(SP,Stack Pointer),专门用于指出堆栈顶部数据的地址. 那么51单片机的堆栈在什么地方呢?由于单片机中存放数据的区域有限,我们不能够专门分配一块地方做堆栈,所以就在内存(RAM ...
- 选择排序(SelectSorted)
//简单的选择排序public class SelectSorted { public static void main(String[] args) { int[] array={12,24,9,7 ...
- LINQ 从 CSV 文件生成 XML
本文参考:http://msdn.microsoft.com/zh-cn/library/bb387090.aspx 下面的代码对字符串数组执行 LINQ 查询. 在 C# 版本中,该查询使用 let ...
- Windows 服务卸载之后 重新安装提示 “指定的服务已标记为删除”
背景: 将一个项目做成一个windows服务,在调试的时候,需要卸载.安装该服务,但提示下面的错误:“指定的服务已标记为删除”,进入服务管理界面,启动自己注册的服务,无法手动更改成启用模 ...
- 《31天成为IT服务达人》之精准运维
1 第十四章精准运维服务 近年来国内IT产业的发展格局始终与我国的经济转型与创新创业的社会大潮息息相关,纵观国内国际形势,IT产业仍是创新的领头者,是解决人类各种经济危机的主要扮演者 ...
- 使用jsdoc-toolkit来自动生成js api文档
近来前端组小盆友开发的类库越来越多,很多情况下彼此不知道写了些什么方法,为了更好的合作提高工作效率,找了个比较好的api文档生成方法.使用jsdoc-toolkit来自动生成js api文档. 一. ...
- linux ptrace I
这几天通过<游戏安全--手游安全技术入门这本书>了解到linux系统中ptrace()这个函数可以实现外挂功能,于是在ubuntu 16.04 x86_64系统上对这个函数进行了学习. 参 ...
- iOS 高仿:花田小憩3.0.1
前言 断断续续的已经学习Swift一年多了, 从1.2到现在的2.2, 一直在语法之间徘徊, 学一段时间, 工作一忙, 再捡起来隔段时间又忘了.思来想去, 趁着这两个月加班不是特别多, 就决定用swi ...
- Android实现多次闪退清除数据
背景 很多时候由于后台返回的数据异常,可能会导致App闪退.而如果这些异常数据被App本地缓存下来,那么即使杀掉进程重新进入还是会发生闪退.唯一的解决方法就是清除App数据,但是用户可能没有这个意识或 ...
- Python中sys.argv[]的用法
类似bash中的$0, $1, $2... sys.argv[0]:文件名 sys.argv[1]:第一个参数 sys.argv[2]:第二个参数 import sys print "The ...