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 ...
随机推荐
- 深入hibernate的三种状态【转载】
这篇文章写得很好,举了很多例子. http://www.cnblogs.com/xiaoluo501395377/p/3380270.html
- CentOS添加swap分区
在多个VPS上尝试. 1.进入目录 cd /var/ 2.获取要增加的SWAP文件块(这里以1GB为例) dd if=/dev/zero of=swapfile bs=1024 count=10383 ...
- 通过例子学python(1)
第一章 基础知识 1.4 数字和表达式 # -*- coding: cp936 -*- # 1.4 数字和表达式 # ** 表示幂(乘方)运算 #1.4.1 长整型数 print(9999999999 ...
- zoj 2100 Seeding
Seeding Time Limit: 2 Seconds Memory Limit: 65536 KB It is spring time and farmers have to plan ...
- 趣味理解ADO.NET对象模型
为了更好地理解ADO.NET的架构模型的各个组成部分,我们可以对ADO.NET中的相关对象进行图示理解,如图所示的是ADO.NET中数据库对象的关系图. 讲究完关系图后,为了加深大家的理解,我们可以用 ...
- 【Jsoup爬取网页内容】
思路:根据给定URL分析其源码,得到所需的网页内容的位置,制定规则采集或下载之 采集的图片和文字示例: tags: tag:brazil tag:dog tag:pet tag:pointyfaced ...
- 用code workshop取代code review
Box Tech Blog » Effective learning through code workshops介绍了Box如何用code workshop而不是code review的形式来改善代 ...
- 【Android - 框架】之刷新加载框架Ultra-Pull-To-Refresh的使用
Ultra-Pull-To-Refresh框架是用来嵌套其他布局,实现下拉刷新和上拉加载的框架.它其中可以嵌套任何控件,ListView.GridView.ScrollView.RecyclerVie ...
- android 56
##其他布局 * LinearLayout * RelativeLayout * FrameLayout * AbsoluteLayout (绝对布局, 文档说过时,应用场景机顶盒开发,定制的平板) ...
- 上传文件时 ContentType 浏览器差异
上传图片时,ie会把 jpg.jpeg翻译成image/pjpeg,png翻译成image/x-png . 火狐.chrome则很标准:jpg.jpeg翻译成image/jpeg,png翻译成imag ...