poj 3468 A Simple Problem with Integers(原来是一道简单的线段树区间修改用来练练splay)
题目链接:http://poj.org/problem?id=3468
题解:splay功能比线段树强大当然代价就是有些操作比线段树慢,这题用splay实现的比线段树慢上一倍。线段树用lazy标记差不多要2s用splay要4s。可以用splay来实现线段树的区间操作更深层次的了解一下splay算是入个门。
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cstdio>
using namespace std;
const int M = 1e5 + ;
typedef long long ll;
int pre[M] , ch[M][] , size[M] , root , tot;//分别表示父节点,左右儿子,大小,根节点,总共的节点数。
int key[M];//当前节点对应的权值
int add[M];//类似懒惰标记
ll sum[M];//当前节点包括他以下的节点权值的总和可以理解为子树权值之和加上这个节点的权值
int a[M];
int n , q;
void NewNode(int &r , int fa , int k) {
r = ++tot;
pre[r] = fa;
size[r] = ;
key[r] = k;
add[r] = ;
sum[r] = ;
ch[r][] = ch[r][] = ;
}//标准的初始化节点
void update(int r , int ad) {
if(r == ) return;
add[r] += ad;
key[r] += ad;
sum[r] += (ll)ad * size[r];
}//节点更新
void push_up(int r) {
size[r] = size[ch[r][]] + size[ch[r][]] + ;
sum[r] = sum[ch[r][]] + sum[ch[r][]] + key[r];
}
void push_down(int r) {
if(add[r]) {
update(ch[r][] , add[r]);
update(ch[r][] , add[r]);
add[r] = ;
}
}//一系列类似线段树的操作。
void Rotate(int x , int kind) {
int y = pre[x];
push_down(y);
push_down(x);
ch[y][!kind] = ch[x][kind];
pre[ch[x][kind]] = y;
if(pre[y]) ch[pre[y]][ch[pre[y]][] == y] = x;
pre[x] = pre[y];
ch[x][kind] = y;
pre[y] = x;
push_up(y);
}
void Splay(int r , int goal) {
push_down(r);
while(pre[r] != goal) {
if(pre[pre[r]] == goal) Rotate(r , ch[pre[r]][] == r);
else {
int y = pre[r];
int kind = (ch[pre[y]][] == y);
if(ch[y][kind] == y) {
Rotate(r , !kind);
Rotate(r , kind);
}
else {
Rotate(y , kind);
Rotate(r , kind);
}
}
}
push_up(r);
if(goal == ) root = r;
}//一系列标准的splay的操作
void build(int &x , int l , int r , int fa) {
if(l > r) return ;
int mid = (l + r) >> ;
NewNode(x , fa , a[mid]);
build(ch[x][] , l , mid - , x);
build(ch[x][] , mid + , r , x);
push_up(x);
}
void init() {
root = , tot = ;
ch[root][] = ch[root][] = pre[root] = size[root] = add[root] = sum[root] = key[root] = ;
NewNode(root , , -);
NewNode(ch[root][] , root , -);
build(ch[ch[root][]][] , , n , ch[root][]);
push_up(root);
push_up(ch[root][]);
}//这里之所以要优先建两个点和后面的更新有关
int get_kth(int r , int k) {
push_down(r);
int t = size[ch[r][]] + ;
if(t == k) return r;
else if(t > k) return get_kth(ch[r][] , k);
else return get_kth(ch[r][] , k - t);
}//获得第几大的数
void ADD(int l , int r , int ad) {
Splay(get_kth(root , l) , );
Splay(get_kth(root , r + ) , root);
update(ch[ch[root][]][] , ad);
push_up(ch[root][]);
push_up(root);
}//这里按照常理应该是将第l-1个节点移到根然后再将r+1的节点移到根的右儿子那么(l~r)就是r+1节点的左儿子的sum值由于之前加了两个节点所以变到了l~r+2,毕竟l-1可能为0就是就是根节点处理起来可能会有些不便。当然无视也行,按照个人喜好来就行。
long long query(int l , int r) {
Splay(get_kth(root , l) , );
Splay(get_kth(root , r + ), root);
return sum[ch[ch[root][]][]];
}//区间查询同理
int main() {
while(scanf("%d%d" , &n , &q) == ) {
for(int i = ; i <= n ; i++) scanf("%d" , &a[i]);
init();
while(q--) {
char c[];
scanf("%s" , c);
if(c[] == 'Q') {
int l , r;
scanf("%d%d" , &l , &r);
printf("%lld\n" , query(l , r));
}
else {
int l , r , x;
scanf("%d%d%d" , &l , &r , &x);
ADD(l , r , x);
}
}
}
return ;
}
poj 3468 A Simple Problem with Integers(原来是一道简单的线段树区间修改用来练练splay)的更多相关文章
- 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(分块入门)
题目链接: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 ...
- 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 线段树区间加,区间查询和
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 ...
- poj 3468:A Simple Problem with Integers(线段树,区间修改求和)
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 58269 ...
随机推荐
- 【SVN】SVN Working copy is too old
前天在使用 SVN 客户端 CornerStone 的时候遇到了这个问题,代码不能提交了…… 遇到这个问题的时候怎么办? 解决办法: 找到报错对应的文件夹,里面有个 .svn 的文件夹,去掉再 com ...
- Vue中动态(import 、require)显示img图片
vue中,经常会遇到显示图片的问题, 如果是一个普通组件的话,那么这样就可以了 <img src="../assets/images/avtor.jpg" width=&qu ...
- 有容云:上车 | 听老司机谈Docker安全合规建设
编者注: 本文根据7月19日DockOne社群分享内容整理而成,分享嘉宾蒋运龙,有容云高级咨询顾问,一个IT的老兵,十年来混迹于存储.三网融合.多屏互动.智能穿戴.第三方支付.Docker等行业:经历 ...
- Java----面向对象(继承&多态)
一.继承 什么是继承 ? 让类与类之间产生了子父类关系 ; 继承的好处是: 提高代码的复用性和维护性 java中继承的特点是: 只支持单继承.不支持多继承,但是可以多层继承; 四种权限修饰符是 : p ...
- MyBatis 简介与入门
简介 什么是 MyBatis ? MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.My ...
- 6.源码分析---和dubbo相比SOFARPC是如何实现负载均衡的?
官方目前建议使用的负载均衡包括以下几种: random(随机算法) localPref(本地优先算法) roundRobin(轮询算法) consistentHash(一致性hash算法) 所以我们接 ...
- Unity经典游戏教程之:贪吃蛇
版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...
- NOIP 2018旅行题解
从佳木斯回来刷一刷去年没A的题 题目描述 小 Y 是一个爱好旅行的 OIer.她来到 X 国,打算将各个城市都玩一遍. 小Y了解到, X国的 nn 个城市之间有 mm 条双向道路.每条双向道路连接两个 ...
- alluxio源码解析-netty部分(2)
netty简介 Netty是 一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端. netty作为alluxio中重要的通讯组件 在常见的客户端上传,下载中,都会有n ...
- [转载]ActiveMQ实现负载均衡+高可用部署方案
转载于 http://www.open-open.com/lib/view/open1400126457817.html 一.架构和技术介绍 1.简介 ActiveMQ 是Apache出品,最流行的, ...