HDU 4348 To the moon (主席树区间更新)
题意:首先给你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 (主席树区间更新)的更多相关文章
- hdu 4348 To the moon (主席树区间更新)
传送门 题意: 一个长度为n的数组,4种操作 : (1)C l r d:区间[l,r]中的数都加1,同时当前的时间戳加1 . (2)Q l r:查询当前时间戳区间[l,r]中所有数的和 . (3)H ...
- hdu 4348 To the moon 主席树区间更新
To the moon Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Prob ...
- HDU 4348 To the moon 主席树 在线更新
http://acm.hdu.edu.cn/showproblem.php?pid=4348 以前做的主席树没有做过在线修改的题做一下(主席树这种东西正经用法难道不是在线修改吗),标记永久化比较方便. ...
- hdu 4348 To the moon (主席树)
版权声明:本文为博主原创文章,未经博主允许不得转载. hdu 4348 题意: 一个长度为n的数组,4种操作 : (1)C l r d:区间[l,r]中的数都加1,同时当前的时间戳加1 . (2)Q ...
- HDU 4348 To the moon 主席树
题意: 给出一个长度为\(n(n \leq 10^5)\)的序列,最开始时间\(t=0\),支持下面几个操作: \(C \, l \, r \, d\):将区间\([l,r]\)每个数都加上\(d\) ...
- HDU 4348 主席树区间更新
To the moon Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total ...
- HDU.1556 Color the ball (线段树 区间更新 单点查询)
HDU.1556 Color the ball (线段树 区间更新 单点查询) 题意分析 注意一下pushdown 和 pushup 模板类的题还真不能自己套啊,手写一遍才行 代码总览 #includ ...
- 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步操作 思路: ...
- HDU 1556 Color the ball(线段树区间更新)
Color the ball 我真的该认真的复习一下以前没懂的知识了,今天看了一下线段树,以前只会用模板,现在看懂了之后,发现还有这么多巧妙的地方,好厉害啊 所以就应该尽量搞懂 弄明白每个知识点 [题 ...
随机推荐
- org.springframework.amqp.rabbit.listener.exception.ListenerExecutionFailedException: Listener threw exception
RabbitMQ 报出的错! org.springframework.amqp.rabbit.listener.exception.ListenerExecutionFailedException ...
- 学习 SSH
ssh_config 与 sshd_config ssh_config: configuration file for the ssh client on the host machine you a ...
- JavaScript数据结构与算法-链表练习
链表的实现 一. 单向链表 // Node类 function Node (element) { this.element = element; this.next = null; } // Link ...
- POI解析Excel封装工具
1. [代码][Java]代码 跳至 [1] [全屏预览] ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 2 ...
- 通过实例来分析I2C基本通信协议
本文旨在用最通俗易懂的方式.让大家明确I2C通信的过程到底是怎么回事. I2C起源于飞利浦公司的电视设计,但之后朝通用路线发展,各种电子设计都有机会用到I2C 总的来说,I2C能够简单归纳为,两根线, ...
- Win10在右键菜单添加“在此处打开命令窗口”设置项
Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\Directory\shell\OpenCmdHere] @="在此处打开命令 ...
- python read文件的r和rb的区别
r,rb,w,wb 那么在读写文件时,有无b标识的的主要区别在哪里呢? 1.文件使用方式标识 'r':默认值,表示从文件读取数据. 'w':表示要向文件写入数据,并截断以前的内容 'a':表示要向文件 ...
- 爬虫五 Beautifulsoup模块详细
一.基本使用 from bs4 import BeautifulSoup htmlCharset = "GB2312" soup=BeautifulSoup(html_doc,'l ...
- css小知识---input输入块
对于如下的界面,介绍一种实现方式. 可以将整个界面分为三块,左中右.通过display: inline-block;和float: right;左右浮动效果实现. 代码如下: <!DOCTYPE ...
- Python与硬件学习笔记:蜂鸣器(转)
相信大家对蜂鸣器都不会陌生,很多产品和方案中都会用到蜂鸣器,大部分都是使用蜂鸣器来做提示或报警,比如按键按下.开始工作.工作结束或是故障等等.这里对单片机在蜂鸣器驱动上的应用作一下描述. 蜂鸣器的介绍 ...