题意:首先给你n个数,开始时间为0,最后按照操作输出

给你四种操作:

1. C l r d :  在(l,r)区间都加上d,时间加一
2. Q l r :  询问现在(l,r)的区间和
3. H l r t :  询问在t的时间(l,r)的区间和
4. B t : 直接回到t的时间

题解:首先是区间修改区间查询,可以想到线段树,接着就是询问历史版本与回到历史版本,这样就是主席树了

首先我们知道普通主席树是单点修改,并支持历史版本的区间求和与回到历史版本(就是这删除之后的树),仅仅只是因为它存了多棵线段树

而我们这儿是要进行区间修改,所以第一反应就是模拟线段树的lazy标记,并在查询时再更新再建树,但是这样会卡空间

因此我们需要这样想,模拟lazy标记进行重建树(最多建立2*log2(n)个节点)是必须的,但是查询时就不需要重建树了

这样我们就需要记录两个值:sum代表这一段中被增加区间的与此这一段的区间相交的总和,com代表这一段都需要增加这么多

这时我们查询时就需要每次加上com与待查询的区间相交的值(加上之前更新的),最后再包含的区间里加上sum再减去这儿com与待查询的区间相交的值(重复了)

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define eps 1E-8
/*注意可能会有输出-0.000*/
#define Sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
#define Cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
#define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0
#define mul(a,b) (a<<b)
#define dir(a,b) (a>>b)
typedef long long ll;
typedef unsigned long long ull;
const int Inf=<<;
const ll INF=1ll<<;
const double Pi=acos(-1.0);
const int Mod=1e9+;
const int Max=1e5+;
int root[Max],tot;
struct node
{
int lef,rig;
ll sum,com;//相交总共的和 这一段每个点都加上这个
}msegtr[Max*];
ll pre[Max];//把原来的数放入前缀和里,主席树里仅仅更新修改的值
void Init(int &cnt)
{
cnt=;
msegtr[].lef=msegtr[].rig=;
msegtr[].sum=msegtr[].com=0ll;
root[]=,tot=;
pre[]=0ll;
return;
}
int Jud(int sta,int enn,int lef,int rig)//关键的区间交
{
return max(min(rig,enn)-max(lef,sta)+,);
}
void Create(int sta,int enn,int &x,int y,int lef,int rig,int com)
{
msegtr[++tot]=msegtr[y];
msegtr[tot].sum+=(ll)com*Jud(sta,enn,lef,rig);
x=tot;
if(sta>=lef&&enn<=rig)//模拟线段树区间更新
{
msegtr[tot].com+=com;//这一段每个点都加上这个
return;
}
int mid=dir(sta+enn,);
if(mid>=lef)
Create(sta,mid,msegtr[x].lef,msegtr[y].lef,lef,rig,com);
if(mid<rig)
Create(mid+,enn,msegtr[x].rig,msegtr[y].rig,lef,rig,com);
return;
}
ll Query(int sta,int enn,int x,int lef,int rig)
{
if(sta>=lef&&enn<=rig)
{
return msegtr[x].sum-msegtr[x].com*Jud(sta,enn,lef,rig);//多加了,要减去
}
int mid=dir(sta+enn,);
ll ans=0ll;
if(mid>=lef)
{
ans+=Query(sta,mid,msegtr[x].lef,lef,rig)+msegtr[msegtr[x].lef].com*Jud(sta,mid,lef,rig);//加上区间交的值
}
if(mid<rig)
{
ans+=Query(mid+,enn,msegtr[x].rig,lef,rig)+msegtr[msegtr[x].rig].com*Jud(mid+,enn,lef,rig);
}
return ans;
}
int main()
{
int n,m,temp,cnt;
int lef,rig,sum;
char str[];
while(~scanf("%d %d",&n,&m))
{
Init(cnt);
for(int i=;i<=n;++i)
{
scanf("%d",&temp);
pre[i]=pre[i-]+temp;
}
for(int i=;i<m;++i)
{
scanf("%s",str);
if(str[]=='C')
{
scanf("%d %d %d",&lef,&rig,&sum);
Create(,n,root[cnt+],root[cnt],lef,rig,sum);
cnt++;
}
else if(str[]=='Q')
{
scanf("%d %d",&lef,&rig);
printf("%I64d\n",Query(,n,root[cnt],lef,rig)+pre[rig]-pre[lef-]);
}
else if(str[]=='H')
{
scanf("%d %d %d",&lef,&rig,&sum);
printf("%I64d\n",Query(,n,root[sum],lef,rig)+pre[rig]-pre[lef-]);
}
else
{
scanf("%d",&sum);
if(sum<cnt)
{
tot=root[sum+];
cnt=sum;//存储线段树,这样就代表摧毁了后面更新的树
}
}
}
}
return ;
}

HDU 4348 To the moon (主席树区间更新)的更多相关文章

  1. hdu 4348 To the moon (主席树区间更新)

    传送门 题意: 一个长度为n的数组,4种操作 : (1)C l r d:区间[l,r]中的数都加1,同时当前的时间戳加1 . (2)Q l r:查询当前时间戳区间[l,r]中所有数的和 . (3)H ...

  2. hdu 4348 To the moon 主席树区间更新

    To the moon Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Prob ...

  3. HDU 4348 To the moon 主席树 在线更新

    http://acm.hdu.edu.cn/showproblem.php?pid=4348 以前做的主席树没有做过在线修改的题做一下(主席树这种东西正经用法难道不是在线修改吗),标记永久化比较方便. ...

  4. hdu 4348 To the moon (主席树)

    版权声明:本文为博主原创文章,未经博主允许不得转载. hdu 4348 题意: 一个长度为n的数组,4种操作 : (1)C l r d:区间[l,r]中的数都加1,同时当前的时间戳加1 . (2)Q ...

  5. HDU 4348 To the moon 主席树

    题意: 给出一个长度为\(n(n \leq 10^5)\)的序列,最开始时间\(t=0\),支持下面几个操作: \(C \, l \, r \, d\):将区间\([l,r]\)每个数都加上\(d\) ...

  6. HDU 4348 主席树区间更新

    To the moon Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  7. HDU.1556 Color the ball (线段树 区间更新 单点查询)

    HDU.1556 Color the ball (线段树 区间更新 单点查询) 题意分析 注意一下pushdown 和 pushup 模板类的题还真不能自己套啊,手写一遍才行 代码总览 #includ ...

  8. HDU 4348 To the moon(主席树 区间更新)题解

    题意: 给一个数组A[1] ~ A[n],有4种操作: Q l r询问l r区间和 C l r v给l r区间每个数加v H l r t询问第t步操作的时候l r区间和 B t返回到第t步操作 思路: ...

  9. HDU 1556 Color the ball(线段树区间更新)

    Color the ball 我真的该认真的复习一下以前没懂的知识了,今天看了一下线段树,以前只会用模板,现在看懂了之后,发现还有这么多巧妙的地方,好厉害啊 所以就应该尽量搞懂 弄明白每个知识点 [题 ...

随机推荐

  1. 16进制 ,Color,Colour转换

    import java.awt.Color; import jxl.format.Colour; public class ColorUtil { public static Colour getNe ...

  2. servlet;jsp;cookies;session

  3. 【BZOJ1823】[JSOI2010]满汉全席 2-SAT

    [BZOJ1823][JSOI2010]满汉全席 Description 满汉全席是中国最丰盛的宴客菜肴,有许多种不同的材料透过满族或是汉族的料理方式,呈现在數量繁多的菜色之中.由于菜色众多而繁杂,只 ...

  4. Chocolate Bar(暴力)

    Chocolate Bar Time limit : 2sec / Memory limit : 256MB Score : 400 points Problem Statement There is ...

  5. IOS开发复习笔记(1)-OC基础知识

    在上班之余学习IOS已经有三个多月了,因为基础有些薄弱从OC的基本语法开始学习的,相继看了青柚子和红柚子的书,现在在看编程实战,趁这个机会好好的总结一下: 1.命名约定 对象类型和名称一致,以免混淆 ...

  6. 原文来自 url get

    w http://www.tuicool.com/articles/BvYbEvR http://36kr.com/p/5069371.html?utm_source=tuicool&utm_ ...

  7. python系列四:Python3字符串

    #!/usr/bin/python #Python3 字符串#可以截取字符串的一部分并与其他字段拼接var1 = 'Hello World!'print ("已更新字符串 : ", ...

  8. Java中volatile关键字实现原理

    原文地址http://www.cnblogs.com/xrq730/p/7048693.html,转载请注明出处,谢谢 前言 我们知道volatile关键字的作用是保证变量在多线程之间的可见性,它是j ...

  9. 2014-08-28——Android和IOS的简单嗅探,以及横竖屏的捕获思路

    一般通过navigator.userAgent来嗅探Android系统和IOS系统: if(/android/i.test(navigator.userAgent)){ //android } if( ...

  10. Nuxt使用Vuex

    Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. 基础知识这里不再重述,学习的话请自行到官网 ...