用树状数组和线段树会比较简单,这里用这道题来学习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. ASP.Net 验证视图状态 MAC 失败

    错误信息: 验证视图状态 MAC 失败.如果此应用程序由网络场或群集承载,请确保 <machineKey> 配置指定了相同的 validationKey 和验证算法.不能在群集中使用 Au ...

  2. IOS7官方推荐图标和图像尺寸

    图标和图像大小 每一个应用程序需要一个应用程序图标和启动图像.此外,一些应用程序需要自定义的图标来表示特定于应用程序的内容,功能,或在导航栏,工具栏和标签栏模式. 不像其他的定制艺术品在您的应用程序的 ...

  3. 自定义UITableView的Seperator

    在默认配置中 ,UITableView的Cell之间的Seperator左边总是空出一块,即使在Storyboard中设置为0 ,也没有效果 需要在代码中进行配置,在ViewController中实现 ...

  4. 【原】Centos6.5下cdh4.6 hive安装部署

    1.前提条件:      只需要选择一台服务器即可,这里选择安装在namenode上:安装用户为cloud-user 2.安装包:      sudo yum install -y hive hive ...

  5. 国内maven镜像

    <mirrors> <mirror> <id>alimaven</id> <name>aliyun maven</name> & ...

  6. Cookie及App登陆的原理

    1.Cookie Cookie意为"甜饼",是由W3C组织提出的.目前Cookie已经成为标准.由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份.怎么办呢?就给 ...

  7. GWT(Google Web Tookit) Eclipse Plugin的zip下载地址(同时提供GWT Designer下载地址)

    按照Eclipse Help->Install new software->....(这里是官方安装文档:http://code.google.com/intl/zh-CN/eclipse ...

  8. Android中GridView拖拽的效果

    最 近看到联想,摩托罗拉等,手机launcher中有个效果,进入mainmenu后,里面的应用程序的图标可以拖来拖去,所以我也参照网上给的代码,写了 一个例子.还是很有趣的,实现的流畅度没有人家的那么 ...

  9. LCA在线算法ST算法

    求LCA(近期公共祖先)的算法有好多,按在线和离线分为在线算法和离线算法. 离线算法有基于搜索的Tarjan算法较优,而在线算法则是基于dp的ST算法较优. 首先说一下ST算法. 这个算法是基于RMQ ...

  10. Merge into的使用具体解释-你Merge了没有

    Merge是一个很实用的功能,相似于Mysql里的insert into on duplicate key. Oracle在9i引入了merge命令,  通过这个merge你可以在一个SQL语句中对一 ...