用树状数组和线段树会比较简单,这里用这道题来学习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 解题报告的更多相关文章

  1. POJ.3468 A Simple Problem with Integers(线段树 区间更新 区间查询)

    POJ.3468 A Simple Problem with Integers(线段树 区间更新 区间查询) 题意分析 注意一下懒惰标记,数据部分和更新时的数字都要是long long ,别的没什么大 ...

  2. poj 3468 A Simple Problem with Integers 【线段树-成段更新】

    题目:id=3468" target="_blank">poj 3468 A Simple Problem with Integers 题意:给出n个数.两种操作 ...

  3. 线段树(成段更新) POJ 3468 A Simple Problem with Integers

    题目传送门 /* 线段树-成段更新:裸题,成段增减,区间求和 注意:开long long:) */ #include <cstdio> #include <iostream> ...

  4. poj 3468 A Simple Problem with Integers(线段树+区间更新+区间求和)

    题目链接:id=3468http://">http://poj.org/problem? id=3468 A Simple Problem with Integers Time Lim ...

  5. POJ 3468 A Simple Problem with Integers(分块入门)

    题目链接:http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit ...

  6. POJ 3468 A Simple Problem with Integers(线段树功能:区间加减区间求和)

    题目链接:http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit ...

  7. [ACM] poj 3468 A Simple Problem with Integers(段树,为段更新,懒惰的标志)

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 55273   ...

  8. 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 ...

  9. 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 ...

随机推荐

  1. Spark SQL利器:cacheTable/uncacheTable

    Spark相对于Hadoop MapReduce有一个很显著的特性就是“迭代计算”(作为一个MapReduce的忠实粉丝,能这样说,大家都懂了吧),这在我们的业务场景里真的是非常有用.   假设我们有 ...

  2. Activity声明周期容易出现的问题

    了解activity的生命周期,不仅仅是回答面试官的几个小问题:下面这篇文章不错,截取个人认为优秀的部分分享给大家,欢迎交流.感谢原作者 /** * 示例向我们展示了在 Activity 的配置改变时 ...

  3. NVIDIA CG语言 函数之所有数学类函数(Mathematical Functions)

    数学类函数(Mathematical Functions) abs(x) 返回标量和向量x的绝对值 如果x是向量,则返回每一个成员的绝对值 acos(x) 返回标量和向量x的反余弦 x的范围是[-1, ...

  4. HDU 4727 The Number Off of FFF 2013年四川省赛题

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4727 题目大意:队列里所有人进行报数,要找出报错的那个人 思路:,只要找出序列中与钱一个人的数字差不是 ...

  5. bzoj 1026 [SCOI2009]windy数(数位DP)

    1026: [SCOI2009]windy数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 4550  Solved: 2039[Submit][Sta ...

  6. 12个强大的Web服务测试工具

    在过去的几年中,web服务或API的普及和使用有所增加. web服务或API是程序或软件组件的集合,可以帮助应用程序进行交互或通过形成其他应用程序或服务器之间的连接执行一些进程/事务处理.基本上有两种 ...

  7. Milk Patterns - poj 3261 (求重复k次的最长子串)

    题目大意:给你一个数组,求这个数组里面至少重复k次的子串.   分析:后缀数组的练手题目...不过给的数字比较大,可以先离散化处理一下即可.   代码如下: ===================== ...

  8. win8.1 无法安装 net framework3.5的解决办法

    近期给重装系统时,发现Windows8.1无法安装.net framework 3.5,即使我离线下载了安装文件,还要求安装2.0和3.0....而且无法从Windows更新中获取,因此百度到以下方案 ...

  9. textarea文本域

    textarea中换行问题 一旦用nl2br函数处理会多个\n导致十分难看 也无法形成文本框默认效果 前台的html如果用<br/>处理也会给后台的编辑造成困难 所以在编辑的时候这样处理 ...

  10. OpenCV 2.4.9

    2014.4.25 感谢那些參加开发.发送错误报告以及通过其它方式帮助我们的全部人和公司. 源代码如今已经可以从SourceForge和Github上下载了. 2.4.9版本号的帮助文章也更新到如今的 ...