虽然有点难,但是这套题都挂了一个月了啊喂……

网上模板好多……最后还是抄了kuangbin聚聚的,毕竟好多模板都是抄他的,比较习惯……

POJ 3468

题意:给n个数,两种操作,区间整体加一个数,或者区间求和。

题解:把区间的前一个数挪到根,区间后一个数挪到根的右子树,根的右子树的左子树就是要处理的区间。。。

SplayTree是一个二叉排序树,它所保存的顺序是数字的编号,所以无论怎样旋转,编号的顺序都不会变。。。

在首尾各插入一个结点,这样求整个区间的时候也可以找到前一个数和后一个数。。。

照了别人的博客写了两遍,自己又裸敲一遍,还是错了好多细节,不过大概理解了。。。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = ;
int sz[N], ch[N][], pre[N];
int a[N];
ll sum[N], add[N], key[N];
int root, tot; void new_node(int &o, int fa, int k) {
o = ++tot;
sz[o] = ;
ch[o][] = ch[o][] = ;
pre[o] = fa;
sum[o] = key[o] = k;
add[o] = ;
} void push_up(int o) {
sum[o] = sum[ch[o][]] + sum[ch[o][]] + key[o];
sz[o] = sz[ch[o][]] + sz[ch[o][]] + ; // +1 !!
} void update(int o, int v) {
if (!o) return ;
add[o] += v;
key[o] += v;
sum[o] += (ll)sz[o]*v;
} void push_down(int o) {
if (add[o]) {
update(ch[o][], add[o]);
update(ch[o][], add[o]);
add[o] = ;
}
} void build(int &o, int l, int r, int fa) {
if (l > r) return;
int mid = (l+r) >> ;
new_node(o, fa, a[mid]);
build(ch[o][], l, mid-, o);
build(ch[o][], mid+, r, o);
push_up(o);
} void init(int n) {
root = tot = ;
sz[] = ch[][] = ch[][] = pre[] = ;
sum[] = add[] = key[] = ;
new_node(root, , -);
new_node(ch[root][], root, -);
build(ch[ch[root][]][], , n, ch[root][]);
push_up(ch[root][]);
push_up(root);
} void rotate(int o, int d) { // 0:left 1:right
int fa = pre[o];
push_down(fa);
push_down(o);
ch[fa][!d] = ch[o][d];
pre[ch[o][d]] = fa;
if (pre[fa]) ch[pre[fa]][ch[pre[fa]][]==fa] = o;
pre[o] = pre[fa];
ch[o][d] = fa;
pre[fa] = o;
push_up(fa);
} void splay(int o, int goal) {
push_down(o);
while (pre[o] != goal) {
if (pre[pre[o]] == goal) {
rotate(o, ch[pre[o]][] == o);
} else {
int fa = pre[o];
int d = (ch[pre[fa]][] == fa);
if (ch[fa][d] == o) {
rotate(o, !d);
rotate(o, d);
} else {
rotate(fa, d);
rotate(o, d);
}
}
}
push_up(o);
if (goal == ) root = o;
} int get_kth(int o, int k) {
push_down(o); //!!
int t = sz[ch[o][]] + ;
if (t == k) return o;
if (t > k) return get_kth(ch[o][], k);
return get_kth(ch[o][], k-t);
} ll query(int l, int r) {
splay(get_kth(root, l), );
splay(get_kth(root, r+), root);
return sum[ ch[ch[root][]][] ];
} void Add(int l, int r, int v) {
splay(get_kth(root, l), );
splay(get_kth(root, r+), root);
update(ch[ch[root][]][], v);
push_up(ch[root][]);
push_up(root);
} int main() {
//freopen("in.txt", "r", stdin);
int n, q;
while (~scanf("%d%d", &n, &q) && n) {
for (int i = ; i <= n; ++i) scanf("%d", a+i);
init(n);
char op[];
int x, y, z;
while (q--) {
scanf("%s%d%d", op, &x, &y);
if (*op == 'Q') {
printf("%lld\n", query(x, y));
} else {
scanf("%d", &z);
Add(x, y, z);
}
}
}
return ;
}

POJ3468--A Simple Problem with Integers(Splay Tree)的更多相关文章

  1. ACM学习历程——POJ3468 A Simple Problem with Integers(线段树)

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

  2. poj3468 A Simple Problem with Integers (树状数组做法)

    题目传送门 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 1 ...

  3. A - 敌兵布阵 ——B - I Hate It——C - A Simple Problem with Integers(线段树)

    C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况.由于 ...

  4. BZOJ3212: Pku3468 A Simple Problem with Integers(线段树)

    3212: Pku3468 A Simple Problem with Integers Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 2530  So ...

  5. Simple Problem with Integers(POJ 3486)

                                                                  A Simple Problem with Integers Time Li ...

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

    https://vjudge.net/problem/POJ-3468 线段树区间更新(lazy数组)模板题 #include<iostream> #include<cstdio&g ...

  7. POJ3468 A Simple Problem with Integers(数状数组||区间修改的RMQ问题)

    You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of op ...

  8. poj3468 A Simple Problem with Integers(线段树/树状数组)

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

  9. kuangbin专题七 POJ3468 A Simple Problem with Integers (线段树或树状数组)

    You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of op ...

随机推荐

  1. 【BZOJ 3343 】 分块

    3343: 教主的魔法 Description 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1. ...

  2. 李洪强iOS开发之静态库

    iOS开发拓展篇—静态库 一.简单介绍 1.什么是库? 库是程序代码的集合,是共享程序代码的一种方式 2.库的分类 根据源代码的公开情况,库可以分为2种类型 (1)开源库 公开源代码,能看到具体实现 ...

  3. VO,DTO,DO,PO的划分

    实体类(VO,DTO,DO)的划分   经常会接触到VO,DO,DTO的概念,本文从领域建模中的实体划分和项目中的实际应用情况两个角度,对这几个概念进行简析. 得出的主要结论是:在项目应用中,VO对应 ...

  4. jquery的ajax向后台servlet传递json类型的多维数组

    后台运行结果:                                                                                      前台运行结果: ...

  5. POJ1850——Code(组合数学)

    Code DescriptionTransmitting and memorizing information is a task that requires different coding sys ...

  6. WinAPI——UnhookWindowsHookEx - 卸掉钩子

    UnhookWindowsHookEx(   hhk: HHOOK {钩子句柄} ): BOOL;    {True/False}

  7. 关于捕获键盘信息的processDialogkey方法2--具体应用

    自定义控件里的keydown方法无法捕获所有的按键消息的处理方法1(自定义控件里的keydown方法无法获取的键值如上下左右键等) 处理办法具体如下: 1.首先在自定义控件UserControl1中重 ...

  8. poj2886Who Gets the Most Candies? (约瑟夫环)

    http://poj.org/problem?id=2886 单点更新 初始位置都是1 如果这个人出去 位置变为0 利用线段树求区间k值 k值的计算如下 如果这个数值是负的 那么下一个人的就是((k- ...

  9. poj2186Popular Cows(强连通分量)

    http://poj.org/problem?id=2186 用tarjan算出强连通分量的个数 将其缩点 连成一棵树  则题目所求即变成求出度为0 的那个节点 在树中是唯一的 即树根 #includ ...

  10. CSS那些事儿-阅读随笔1(CSS简介与选择符)

    最近开始详细钻研CSS有关的知识,参考资料是<CSS那些事儿>.将把在此过程中的收获进行记录,方便以后的学习. 一.CSS简介 1.什么是CSS CSS全称为Cascading Style ...