用splay做了一遍。

建树时是按照数列序号从小到大排好的,每个节点左子树的序号小于右子树的序号及这个节点本身。
由于查询[l,r]要伸展l-1,r+1所以我们要多加2个结点,保证边界处理时不出问题。由于这样每次查找l-1时,
要找的应该是l(r+1也是找r+2)。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define ll __int64
#define key_value ch[ch[root][1]][0]
using namespace std;
const int MAXN=;
int pre[MAXN],ch[MAXN][],key[MAXN],tot1,root;
int siz[MAXN],tot2,a[MAXN],n,s[MAXN];
ll lazy[MAXN],sum[MAXN]; void Treavel(int x)
{
if(x)
{
Treavel(ch[x][]);
printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d,key=%2d add=%2d sum=%I64d\n",x,ch[x][],ch[x][],pre[x],siz[x],key[x],lazy[x],sum[x]);
Treavel(ch[x][]);
}
}
void debug()
{
printf("root:%d\n",root);
Treavel(root);
} void Newnode(int &rt,int father,int k)
{
if(tot2)
rt = s[--tot2];
else
rt = ++tot1;
pre[rt] = father;
key[rt] = k;
siz[rt] = ;
lazy[rt] = ;
ch[rt][] = ch[rt][] = ;
}
void pushup(int rt)
{
siz[rt] = siz[ch[rt][]] + siz[ch[rt][]] + ;
sum[rt] = sum[ch[rt][]] + sum[ch[rt][]] + key[rt];
}
void pushdown(int rt)
{
if(lazy[rt]){
lazy[ch[rt][]] += lazy[rt];
lazy[ch[rt][]] += lazy[rt];
key[ch[rt][]] += lazy[rt];
key[ch[rt][]] += lazy[rt];
sum[ch[rt][]] += (ll)siz[ch[rt][]]*lazy[rt];
sum[ch[rt][]] += (ll)siz[ch[rt][]]*lazy[rt];
lazy[rt] = ;
}
}
void build(int &rt,int l,int r,int father)
{
if(l > r)
return ;
int m = (l+r)/;
Newnode(rt,father,a[m]);
build(ch[rt][],l,m-,rt);
build(ch[rt][],m+,r,rt);
pushup(rt);
}
void Init()
{
int i,j;
for(i=; i<=n; i++){
scanf("%d",&a[i]);
}
root = tot1 = tot2 = ;
ch[root][] = ch[root][] = key[root] = siz[root] = lazy[root] = pre[root] = sum[root] = ;
Newnode(root,,-);
Newnode(ch[root][],root,-);//头尾各加入一个点
build(key_value,,n,ch[root][]);//让所有数据夹在这两个点之间 由于树的结构 所以在ch[ch[root][1]][0]
pushup(ch[root][]);
pushup(root);
}
void Rotate(int rt,int kind)
{
int y = pre[rt];
pushdown(y);
pushdown(rt);
ch[y][!kind] = ch[rt][kind];
pre[ch[rt][kind]] = y;
if(pre[y]){
ch[pre[y]][ch[pre[y]][]==y] = rt;
}
pre[rt] = pre[y];
ch[rt][kind] = y;
pre[y] = rt;
pushup(y);
}
void splay(int rt,int goal)
{
pushdown(rt);
while(pre[rt] != goal)
{
if(pre[pre[rt]] == goal){
Rotate(rt,ch[pre[rt]][]==rt);
}
else {
int y = pre[rt];
int kind = ch[pre[y]][]==y;
if(ch[y][kind] == rt){
Rotate(rt,!kind);
Rotate(rt,kind);
}
else {
Rotate(y,kind);
Rotate(rt,kind);
}
}
}
pushup(rt);
if(goal == )
root = rt; }
int Get_kth(int rt,int k)
{
pushdown(rt);
int t = siz[ch[rt][]] + ;
if(t == k){
return rt;
}
else if(t > k){
return Get_kth(ch[rt][],k);
}
else
return Get_kth(ch[rt][],k-t);
}
void updata(int l,int r,int v)
{
splay(Get_kth(root,l),);
splay(Get_kth(root,r+),root);
key[key_value] += v;
lazy[key_value] += v;
sum[key_value] += (ll)v*siz[key_value];
}
ll query(int l,int r)
{
splay(Get_kth(root,l),);//由于开始的时候多添加了2个结点,所以编号都是在这2个结点之间的 所以查询的时候都要大1
splay(Get_kth(root,r+),root);
return sum[key_value];
}
int main()
{
int i,j,q;
while(~scanf("%d%d",&n,&q))
{
Init();
//debug();
char s[];
while(q--)
{
scanf("%s",s);
if(s[] == 'C'){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
updata(x,y,z);
}
else {
int x,y;
scanf("%d%d",&x,&y);
printf("%I64d\n",query(x,y));
}
}
}
}

poj3468 splay(成段跟新 区间求和)的更多相关文章

  1. UESTC-1057 秋实大哥与花(线段树+成段加减+区间求和)

    秋实大哥与花 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit St ...

  2. 线段树(成段更新,区间求和lazy操作 )

    hdu1556 Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/O ...

  3. POJ-3468 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 ...

  4. POJ 3468.A Simple Problem with Integers-线段树(成段增减、区间查询求和)

    POJ 3468.A Simple Problem with Integers 这个题就是成段的增减以及区间查询求和操作. 代码: #include<iostream> #include& ...

  5. poj 3468 A Simple Problem with Integers (线段树 成段更新 加值 求和)

    题目链接 题意: 只有这两种操作 C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.&quo ...

  6. POJ 3225.Help with Intervals-线段树(成段替换、区间异或、简单hash)

    POJ3225.Help with Intervals 这个题就是对区间的各种操作,感觉这道题写的一点意思都没有,写到后面都不想写了,而且更神奇的是,自己的编译器连结果都输不出来,但是交上就过了,也是 ...

  7. poj_3468线段树成段更新求区间和

    #include<iostream> #include<string.h> #include<cstdio> long long num[100010]; usin ...

  8. 线段树---poj3468 A Simple Problem with Integers:成段增减:区间求和

    poj3468 A Simple Problem with Integers 题意:O(-1) 思路:O(-1) 线段树功能:update:成段增减 query:区间求和 Sample Input 1 ...

  9. poj3468 A Simple Problem with Integers(线段树模板 功能:区间增减,区间求和)

    转载请注明出处:http://blog.csdn.net/u012860063 Description You have N integers, A1, A2, ... , AN. You need ...

随机推荐

  1. [cocos2dx]利用NDK崩溃日志查找BUG

    摘要: 在android上开发c++应用, crash日志都是汇编码, 很难对应到c++代码中去. 通过此文, 你可以定位到程序崩溃时的C++代码, 精确查找问题. 博客: http://www.cn ...

  2. 分享一个Fluent风格的邮件发送封装类

    C#中用SmtpClient发邮件很简单,闲着无事,简单封装一下 IEmailFactory public interface IEmailFactory { IEmailFactory SetHos ...

  3. JS实现图片上传预览效果:方法一

    <script type="text/javascript"> //处理file input加载的图片文件 $(document).ready(function(e) ...

  4. JSP中文乱码问题《转》

    之前总是碰到JSP页面乱码的问题,每次都是现在网上搜,然后胡乱改,改完也不明白原因. 这次正好作下总结,中文乱码就是因为编码不符,可能出现乱码有四个地方: 1 JSP编码乱码 2 HTML编码乱码 3 ...

  5. unity3D里面的点乘和叉乘

    在unity3D里面.两个向量的点乘所得到的是两个向量的余弦值,也就是-1 到1之间,0表示垂直,-1表示相反,1表示相同方向. 两个向量的叉乘所得到的是两个向量所组成的面的垂直向量,分两个方向. 简 ...

  6. flex4 s:Datagrid <s:typicalItem

    <s:DataGird <s:typicalItem 这个标签相信大家很陌生吧, 我也是今天准备讲的时候才看到,估计是 flex4.5.1 新加东西,果然摸索 了下,这个标签作用也蛮好用的 ...

  7. 解决Linux中java.net.UnknownHostException: oracledb.sys.iflashbuy.com问题

    Linux环境报java.net.UnknownHostException: oracledb.sys.iflashbuy.com,原因为Linux下无法解析oracledb.sys.iflashbu ...

  8. android strings.xml 报 is not translated in af,

    57 down vote In your ADT go to window->Preferences->Android->Lint Error Checking Find there ...

  9. Windows 2008 R2 配置 DNS 实现二级域名

    本文内容 域名解析 准备工作 安装 DNS 服务器 建立 DNS 区域 建立主机头 服务器网络设置 测试二级域名 IIS 建立 Web 站点 其他 DNS 服务 域名解析 域名解析,是域名到 IP 地 ...

  10. rsync+inotify实时同步环境部署记录

    随着应用系统规模的不断扩大,对数据的安全性和可靠性也提出的更好的要求,rsync在高端业务系统中也逐渐暴露出了很多不足.首先,rsync在同步数据时,需要扫描所有文件后进行比对,进行差量传输.如果文件 ...