[HDU4348]To the moon(主席树+标记永久化)
学可持久化treap的时候才发现自己竟然没写过需要标记下传的主席树,然而现在发现大部分操作都可以标记永久化,下传会增大占用空间。
这题一种写法是和普通的线段树一样标记下传,注意所有修改操作(包括put())都要新建点。于是MLE了。
#include<cstdio>
#include<algorithm>
#define lson v[x].ls,L,mid
#define rson v[x].rs,mid+1,R
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
typedef long long ll;
using namespace std; const int N=;
char op;
int n,m,l,r,k,tim,nd,a[N],rt[N];
struct Tr{ int ls,rs; ll sm,tag; }v[N*]; void put(int &x,int L,int R,ll k){ if (x) v[++nd]=v[x],x=nd,v[nd].sm+=(R-L+)*k,v[nd].tag+=k; } void push(int x,int L,int R){ int mid=(L+R)>>; if (v[x].tag) put(lson,v[x].tag),put(rson,v[x].tag),v[x].tag=; } void build(int &x,int L,int R){
x=++nd;
if (L==R){ v[x]=(Tr){,,a[L],}; return; }
int mid=(L+R)>>;
build(lson); build(rson);
v[x].sm=v[v[x].ls].sm+v[v[x].rs].sm; v[x].tag=;
} void ins(int y,int &x,int L,int R,int l,int r,int k){
x=++nd; v[x]=v[y];
if (L==l && r==R){ v[x].sm+=1ll*(R-L+)*k; v[x].tag+=k; return; }
int mid=(L+R)>>; push(x,L,R);
if (r<=mid) ins(v[y].ls,lson,l,r,k);
else if (l>mid) ins(v[y].rs,rson,l,r,k);
else ins(v[y].ls,lson,l,mid,k),ins(v[y].rs,rson,mid+,r,k);
v[x].sm=v[v[x].ls].sm+v[v[x].rs].sm;
} ll que(int x,int L,int R,int l,int r){
if (L==l && r==R) return v[x].sm;
int mid=(L+R)>>; push(x,L,R);
if (r<=mid) return que(lson,l,r);
else if (l>mid) return que(rson,l,r);
else return que(lson,l,mid)+que(rson,mid+,r);
} int main(){
freopen("hdu4348.in","r",stdin);
freopen("hdu4348.out","w",stdout);
while (~scanf("%d%d",&n,&m)){
rep(i,,n) scanf("%d",&a[i]);
nd=tim=; build(rt[],,n);
rep(i,,m){
scanf(" %c",&op);
if (op=='C') scanf("%d%d%d",&l,&r,&k),tim++,ins(rt[tim-],rt[tim],,n,l,r,k);
if (op=='Q') scanf("%d%d",&l,&r),printf("%lld\n",que(rt[tim],,n,l,r));
if (op=='H') scanf("%d%d%d",&l,&r,&k),printf("%lld\n",que(rt[k],,n,l,r));
if (op=='B') scanf("%d",&k),tim=k;
}
puts("");
}
return ;
}
未永久化(MLE)
另一种写法就是标记永久化,若一个修改区间覆盖当前区间则将tag+=k,但并不下传。询问时将答案加上tag的贡献即可。
注意多组数据的清空问题。
#include<cstdio>
#include<algorithm>
#define lson v[x].ls,L,mid
#define rson v[x].rs,mid+1,R
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
typedef long long ll;
using namespace std; const int N=;
char op;
int n,m,l,r,k,tim,nd,flag,a[N],rt[N];
struct Tr{ int ls,rs; ll sm,tag; }v[N*]; void build(int &x,int L,int R){
x=++nd;
if (L==R){ v[x]=(Tr){,,a[L],}; return; }
int mid=(L+R)>>;
build(lson); build(rson);
v[x].sm=v[v[x].ls].sm+v[v[x].rs].sm; v[x].tag=;
} void ins(int y,int &x,int L,int R,int l,int r,int k){
x=++nd; v[x]=v[y]; v[x].sm+=1ll*(r-l+)*k;
if (L==l && r==R){ v[x].tag+=k; return; }
int mid=(L+R)>>;
if (r<=mid) ins(v[y].ls,lson,l,r,k);
else if (l>mid) ins(v[y].rs,rson,l,r,k);
else ins(v[y].ls,lson,l,mid,k),ins(v[y].rs,rson,mid+,r,k);
} ll que(int x,int L,int R,int l,int r){
if (L==l && r==R) return v[x].sm;
int mid=(L+R)>>,res=v[x].tag*(r-l+);
if (r<=mid) return res+que(lson,l,r);
else if (l>mid) return res+que(rson,l,r);
else return res+que(lson,l,mid)+que(rson,mid+,r);
} int main(){
freopen("hdu4348.in","r",stdin);
freopen("hdu4348.out","w",stdout);
while (~scanf("%d%d",&n,&m)){
if (flag) puts(""); else flag=;
rep(i,,n) scanf("%d",&a[i]);
nd=tim=; build(rt[],,n);
rep(i,,m){
scanf(" %c",&op);
if (op=='C') scanf("%d%d%d",&l,&r,&k),tim++,ins(rt[tim-],rt[tim],,n,l,r,k);
if (op=='Q') scanf("%d%d",&l,&r),printf("%lld\n",que(rt[tim],,n,l,r));
if (op=='H') scanf("%d%d%d",&l,&r,&k),printf("%lld\n",que(rt[k],,n,l,r));
if (op=='B') scanf("%d",&tim);
}
}
return ;
}
[HDU4348]To the moon(主席树+标记永久化)的更多相关文章
- hdu4348区间更新的主席树+标记永久化
http://acm.hdu.edu.cn/showproblem.php?pid=4348 sb的标记永久化即可,刚开始add和sum没复制过来wa了两发...,操作和原来的都一样,出来单点变成区间 ...
- SP11470 TTM - To the moon[主席树标记永久化]
SP11470 TTM - To the moon C l r d:区间 \([L,R]\) 中的数都加 d ,同时当前的时间戳加 1. Q l r:查询当前时间戳区间 \([L,R]\) 中所有数的 ...
- Codeforces 258E - Little Elephant and Tree(根号暴力/线段树+标记永久化/主席树+标记永久化/普通线段树/可撤销线段树,hot tea)
Codeforces 题目传送门 & 洛谷题目传送门 yyq:"hot tea 不常有,做过了就不能再错过了" 似乎这是半年前某场 hb 模拟赛的 T2?当时 ycx.ym ...
- [HNOI2015]开店(树剖+主席树+标记永久化)
听说正解点分树?我不会就对了 此题是 \([LNOI2014]LCA\) 强化版,也是差分一下,转化为区间加区间和 不过权值有大小要求,那么我们按照权值排序,依次加入主席树,询问的时候 \(lower ...
- HDU 4348(主席树 标记永久化)
题面一看就是裸的数据结构题,而且一看就知道是主席树... 一共四种操作:1:把区间[l, r]的数都加上d,并且更新时间.2:查询当前时间的区间和.3:查询历史时间的区间和.4:时光倒流到某个时间. ...
- hdu4348 To the moon (主席树 || 离线线段树)
Problem Description Background To The Moon is a independent game released in November 2011, it is a ...
- BZOJ4785 [Zjoi2017]树状数组 【二维线段树 + 标记永久化】
题目链接 BZOJ4785 题解 肝了一个下午QAQ没写过二维线段树还是很难受 首先题目中的树状数组实际维护的是后缀和,这一点凭分析或经验或手模观察可以得出 在\(\mod 2\)意义下,我们实际求出 ...
- HDU 4348 To the moon 主席树 在线更新
http://acm.hdu.edu.cn/showproblem.php?pid=4348 以前做的主席树没有做过在线修改的题做一下(主席树这种东西正经用法难道不是在线修改吗),标记永久化比较方便. ...
- hdu 4348 To the moon (主席树区间更新)
传送门 题意: 一个长度为n的数组,4种操作 : (1)C l r d:区间[l,r]中的数都加1,同时当前的时间戳加1 . (2)Q l r:查询当前时间戳区间[l,r]中所有数的和 . (3)H ...
随机推荐
- C语言复习---迭代法,牛顿迭代法,二分法求根
一:用迭代法求 x=√a.求平方根的迭代公式为:X(n+1)=(Xn+a/Xn) /2. #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> ...
- 阿里云(一)云存储OSS的命令行osscmd的安装和使用
一.安装Python 在Linux Shell里验证Python版本: $ python -V Python 2.7.10 二.安装OSScmd SDK osscmd是基于python 2.5.4(其 ...
- 转 -----那些年总也记不牢的IO
关于资源关闭: 一般情况下是:先打开的后关闭,后打开的先关闭 另一种情况:看依赖关系,如果流a依赖流b,应该先关闭流a,再关闭流b 例如处理流a依赖节点流b,应该先关闭处理流a,再关闭节点流b 当然完 ...
- Docker 入门 第二部分: 容器
目录 Docker 入门 第二部分: 容器 先决条件 介绍 你的新开发环境 使用 Dockerfile 定义一个容器 Dockerfile 应用本身 requirements.txt app.py 构 ...
- Kafka 温故(五):Kafka的消费编程模型
Kafka的消费模型分为两种: 1.分区消费模型 2.分组消费模型 一.分区消费模型 二.分组消费模型 Producer : package cn.outofmemory.kafka; import ...
- 数链剖分(树的统计Count )
题目链接:https://cn.vjudge.net/contest/279350#problem/C 具体思路:单点更新,区间查询,查询的时候有两种操作,查询区间最大值和区间和. 注意点:在查询的时 ...
- 云计算--hdfs dfs 命令
在hadoop安装目录下:/hadoop2/hadoop-2.7.3 1.创建目录 bin/hdfs dfs -mkdir /user bin/hdfs dfs -mkdir /user/<us ...
- 【转载】linux ls -l命令详解
Linux 文件或目录的属性主要包括:文件或目录的节点.种类.权限模式.链接数量.所归属的用户和用户组.最近访问或修改的时间等内容.具体情况如下: 命令: ls -lih 输出: [root@loca ...
- Linux USB Host-Controller的初始化代码框架分析【转】
转自:http://blog.csdn.net/zkami/article/details/2496770 usb_hcd_omap_probe (const struct hc_driver *dr ...
- expect学习笔记及实例详解【转】
1. expect是基于tcl演变而来的,所以很多语法和tcl类似,基本的语法如下所示:1.1 首行加上/usr/bin/expect1.2 spawn: 后面加上需要执行的shell命令,比如说sp ...