伸展数最基本操作的模板,区间求和,区间更新。为了方便理解,特定附上一自己搞的搓图

这是样例中的数据输入后建成的树,其中的1,2是加入的边界顶点,数字代表节点编号,我们如果要对一段区间[l, r]进行操作,只需要把第l-1位的数旋转到0节点下面,把r+1位的数旋转到当前的root下面,就如上图所示,那么椭圆里表示的就是区间[l, r]。

附上注释代码。指针版本的比静态数组的快1s多。。

/* **********************************************
Author : JayYe
Created Time: 2013-8-16 11:14:36
File Name : zzz.cpp
*********************************************** */ #include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std; #define LL __int64
#define keytree (ch[ ch[root][1] ][0])
#define lson ch[x][0]
#define rson ch[x][1] const int maxn = 111111; struct Splaytree { int pre[maxn], ch[maxn][2], sz[maxn];
int root, top;
// 旋转操作, c = 0代表左旋, c = 1代表右旋
void Rotate(int x, int c) {
int y = pre[x];
push_down(y), push_down(x);
ch[y][!c] = ch[x][c];
pre[ch[x][c]] = y;
if(pre[y]) ch[pre[y]][ ch[pre[y]][1] == y ] = x;
pre[x] = pre[y];
ch[x][c] = y;
pre[y] = x;
push_up(y);
}
// Splay 操作, 把 x 节点转到go的下面
void Splay(int x, int go) {
while(pre[x] != go) {
if(pre[pre[x]] == go) {
Rotate(x, ch[pre[x]][0] == x);
}
else {
int y = pre[x] , z = pre[y];
int f = (ch[z][1] == y);
if(ch[y][f] == x)
Rotate(y, !f), Rotate(x, !f); // 一字型旋转
else
Rotate(x, f), Rotate(x, !f); // 之字型旋转
}
}
push_up(x);
if(go == 0) root = x;
}
// 将第k位的数旋转到go的下面
void RotateTo(int k, int go) {
int x = root;
push_down(root);
while(sz[lson] != k) {
if(k < sz[lson]) {
x = lson;
}
else {
k -= sz[lson] + 1;
x = rson;
}
push_down(x);
}
Splay(x, go);
} void debug() {printf("%d\n",root);Treaval(root);}
void Treaval(int x) {
if(x) {
Treaval(ch[x][0]);
printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x]);
Treaval(ch[x][1]);
}
} int val[maxn], add[maxn], a[maxn];
LL sum[maxn];
// 把儿子节点的信息更新上来
void push_up(int x) {
sz[x] = sz[lson] + sz[rson] + 1;
sum[x] = val[x] + add[x] + sum[lson] + sum[rson];
}
// 标记下传
void push_down(int x) {
if(add[x]) {
val[x] += add[x];
add[lson] += add[x];
add[rson] += add[x];
sum[lson] += (LL)add[x]*sz[lson];
sum[rson] += (LL)add[x]*sz[rson];
add[x] = 0;
}
} void newnode(int &x, int c) {
x = ++top;
lson = rson = 0;
sz[x] = 1;
val[x] = sum[x] = c;
add[x] = 0;
} void build(int &x, int l, int r, int f) {
if(l > r) return ;
int mid = (l+r)/2;
newnode(x, a[mid]);
build(lson, l, mid-1, x);
build(rson, mid+1, r, x);
pre[x] = f;
push_up(x);
} void init(int n) {
ch[0][0] = ch[0][1] = pre[0] = 0;
top = root = 0;
newnode(root, -1);
newnode(ch[root][1], -1);
// 为了方便处理边界,加两个边界顶点
pre[top] = root;
sz[root] = 2; for(int i = 0;i < n; i++) scanf("%d", &a[i]);
build(keytree, 0, n-1, ch[root][1]);
push_up(ch[root][1]);
push_up(root);
} void update(int l ,int r, int c) {
RotateTo(l-1, 0);
RotateTo(r+1, root);
add[keytree] += c;
sum[keytree] += (LL)c*sz[keytree];
} LL query(int l, int r) {
RotateTo(l-1, 0);
RotateTo(r+1, root);
return sum[keytree];
} }spt; int main() {
int n, m, l, r, c;
char s[2];
scanf("%d%d", &n, &m);
spt.init(n);
while(m--) {
scanf("%s%d%d", s, &l, &r);
if(s[0] == 'Q')
printf("%I64d\n", spt.query(l, r));
else {
scanf("%d", &c);
spt.update(l, r, c);
}
}
return 0;
}
/* **********************************************
Author : JayYe
Created Time: 2013-8-16 15:19:38
File Name : zzz.cpp
*********************************************** */ #include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std; #define LL __int64
#define keytree (root->ch[1]->ch[0])
#define lson x->ch[0]
#define rson x->ch[1] const int maxn = 111111; struct NODE {
struct NODE *ch[2], *pre;
int add, val, sz, id;
LL sum;
void push_down() {
if(add) {
val += add;
if(ch[0]) {
ch[0]->add += add;
ch[0]->sum += (LL)add*ch[0]->sz;
}
if(ch[1]) {
ch[1]->add += add;
ch[1]->sum += (LL)add*ch[1]->sz;
}
add = 0;
}
} void push_up() {
sz = ch[0]->sz + ch[1]->sz + 1;
sum = val + add + ch[0]->sum + ch[1]->sum;
} }node[maxn], *null = &node[0], *root; struct Splaytree { int top;
// 旋转操作, c = 0代表左旋, c = 1代表右旋
void Rotate(NODE *x, int c) {
NODE *y = x->pre;
y->push_down(), x->push_down();
y->ch[!c] = x->ch[c];
x->ch[c]->pre = y;
x->pre = y->pre;
if(y->pre != NULL) y->pre->ch[ y->pre->ch[1] == y] = x;
x->ch[c] = y;
y->pre = x;
y->push_up();
}
// Splay 操作, 把 x 节点转到go的下面
void Splay(NODE *x, NODE *go) {
while(x->pre != go) {
if(x->pre->pre == go) {
Rotate(x, x->pre->ch[0] == x);
}
else {
NODE *y = x->pre, *z = y->pre;
int f = (z->ch[1] == y);
if(y->ch[f] == x)
Rotate(y, !f) , Rotate(x, !f); // 一字型旋转
else
Rotate(x, f) , Rotate(x, !f); // 之字型旋转
}
}
x->push_up();
if(go == null) root = x;
}
// 将第k位的数旋转到go的下面
void RotateTo(int k, NODE *go) {
NODE *x = root;
x->push_down();
while(lson->sz != k) {
if(lson->sz > k) {
x = lson;
}
else {
k -= lson->sz + 1;
x = rson;
}
x->push_down();
}
Splay(x, go);
} void debug(NODE *x) {
if(x != null) {
printf("节点: %2d 左儿子: %2d 右儿子: %2d size = %2d val = %2d\n",
x->id, x->ch[0]->id, x->ch[1]->id, x->sz, x->val);
debug(x->ch[0]);
debug(x->ch[1]);
}
} int a[maxn]; NODE *newnode(NODE* f, int c) {
NODE *x = &node[++top];
x->id = top;
x->val = x->sum = c;
x->ch[0] = x->ch[1] = null;
x->sz = 1;
x->add = 0;
x->pre = f;
return x;
} void build(NODE* &x, int l, int r, NODE *f) {
if(l > r) return ;
int mid = (l+r)/2;
x = newnode(f, a[mid]);
build(lson, l, mid-1, x);
build(rson, mid+1, r, x);
x->push_up();
} void init(int n) {
null->id = 0;
null->ch[0] = null->ch[1] = NULL;
null->sz = null->add = null->sum = null->val = 0;
// null->pre = NULL;
top = 0;
root = newnode(null, -1);
root->ch[1] = newnode(root, -1); for(int i = 0;i < n; i++) scanf("%d", &a[i]);
build(keytree, 0, n-1, root->ch[1]);
root->ch[1]->push_up(); root->push_up();
} void update() {
int l, r, c;
scanf("%d%d%d", &l, &r, &c);
RotateTo(l-1, null);
RotateTo(r+1, root);
keytree->add += c;
keytree->sum += (LL)c*keytree->sz;
} void query() {
int l, r;
scanf("%d%d", &l, &r);
RotateTo(l-1, null);
RotateTo(r+1, root);
printf("%I64d\n", keytree->sum);
}
}spt; int main() {
int n, m;
char s[2];
scanf("%d%d", &n, &m);
spt.init(n);
while(m--) {
scanf("%s", s);
if(s[0] == 'Q')
spt.query();
else
spt.update();
}
return 0;
}

POJ 3468 A Simple Problem with Integers (伸展树区间更新求和操作 , 模板)的更多相关文章

  1. [POJ] 3468 A Simple Problem with Integers [线段树区间更新求和]

    A Simple Problem with Integers   Description You have N integers, A1, A2, ... , AN. You need to deal ...

  2. poj 3468 A Simple Problem with Integers (线段树区间更新求和lazy思想)

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

  3. poj 3468 A Simple Problem with Integers 线段树区间更新

    id=3468">点击打开链接题目链接 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072 ...

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

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

  5. (简单) POJ 3468 A Simple Problem with Integers , 线段树+区间更新。

    Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. On ...

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

    题目地址:POJ 3468 打了个篮球回来果然神经有点冲动. . 无脑的狂交了8次WA..竟然是更新的时候把r-l写成了l-r... 这题就是区间更新裸题. 区间更新就是加一个lazy标记,延迟标记, ...

  7. POJ 3468 A Simple Problem with Integers(线段树区间更新,模板题,求区间和)

    #include <iostream> #include <stdio.h> #include <string.h> #define lson rt<< ...

  8. POJ 3468 A Simple Problem with Integers 线段树 区间更新

    #include<iostream> #include<string> #include<algorithm> #include<cstdlib> #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. C#和asp.net执行外部EXE程序

    这两天研究下.Net的执行外部EXE程序问题,就是在一个程序里通过按钮或其他操作运行起来另外一个程序,需要传入参数,如用户名.密码之类(实际上很类似单点登录,不过要简单的多的多):总结如下: 1.CS ...

  2. 802.11 wireless 四

    802.11 wireless 4spread spectrum(扩频 - 基于香农定理的算法)1.窄带和扩频是发送信号的两种不同方式2.扩频技术使用更小的能量在波峰3.带宽的需要,基于发送数据的量频 ...

  3. delete错误

    今天找了半天delete错误,后来才知道是MTd和MDd模式的问题,MTd的内存申请和释放必须在同一个模块里面,接口上面不能使用stl等,MDd可以使用.改成MDd就可以了

  4. TGL 月光精品教程整理

    月光站群培训班目录(不定时更新中) wordpress快速配置,插件,模板知识汇总(不定期更新) 适合国人的英文站思维(1) 英语思维-送给正在苦于学英语的童鞋 做seo的重要心态 seo排名难易度分 ...

  5. JavaScript之引用类型讲解

    Object类型 Object类型是JavaScript中使用最多的一种类型.虽然Object的实例不具备多少功能,但对于在应用程序中存储和传输数据而言,它确实是非常理想的选择. 创建Object实例 ...

  6. 从maya导入物体 Importing Objects From Maya

    原地址:http://game.ceeger.com/Manual/HOWTO-ImportObjectMaya.html Unity natively imports Maya files. To ...

  7. MariaDB Galera Cluster 部署(如何快速部署 MariaDB 集群)

    MariaDB Galera Cluster 部署(如何快速部署 MariaDB 集群)  OneAPM蓝海讯通7月3日 发布 推荐 4 推荐 收藏 14 收藏,1.1k 浏览 MariaDB 作为 ...

  8. SELINUX设为Disable 影响java SSH工具包Jsch 0.1.49.jar的一个案例

    最近项目中遇到一个典型事件,当RHEL 的SELINUX设为DISABLE时 使用JAVA的Jsch 库调用SSH命令时将随机返回空字符串,我使用的版本是0.1.49,最新版本0.1.51未测试. 关 ...

  9. opal 将ruby代码转化成javascript

    点这里 https://github.com/opal Opal    Opal is a ruby to javascript source-to-source compiler. It also ...

  10. struts.properties的参数描述

    A.2.1 概述 如果我们希望覆盖在default.properties文件里面定义的默认配置,那就可以定义struts.properties文件,在里面设置我们需要的值,当然现在也可以在struts ...