SPOJ - TTM 主席树
给你一个系列\(a[1...n]\),要求可以区间求和,区间更新,也可以回溯过去
经典的主席树板子题,很久以前做的题了,代码太丑回炉重写
PS.题目标题To The Moon也是我最喜欢的游戏之一
这回纯手写(美化)了一遍,意外踩坑了orz
1.不考虑空间开销可使用确实可以pushdown而不使用标记永久化,具体可以pushdown的时候另开左右儿子新节点
2.一个简易可行的节点回收方案是每一个时间戳记录最后一个更新到的节点id
3.可持久化标记是某节点的lazy表示该节点以下的懒惰标记,注意不动态更新sum只更lazy是无法保证上传正确的(曾经天真的以为..)
4.注意了lazy直接打到sum永久化之后还需注意不要pushup sum值,否则就是把下面的标记化的sum传上去等价于破坏标记.敲板子一般不会注意,自己手写debug了很久
明天开坑BZOJ
#include<bits/stdc++.h>
#include<unordered_map>
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define rrep(i,j,k) for(int i=j;i>=k;i--)
#define erep(i,u) for(int i=head[u];~i;i=nxt[i])
#define print(a) printf("%lld",(ll)(a))
#define printbk(a) printf("%lld ",(ll)(a))
#define println(a) printf("%lld\n",(ll)(a))
using namespace std;
const int MAXN = 1e5+11;
typedef long long ll;
ll read(){
ll x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int a[MAXN];
struct FST{
int lc[MAXN<<5],rc[MAXN<<5],delta[MAXN<<5];
ll sum[MAXN<<5];
int T[MAXN],ed[MAXN],tot;
void init(){
tot=0;
}
void pu(int o){
sum[o]=sum[lc[o]]+sum[rc[o]];
}
int build(int l,int r){
int cur=++tot;
delta[cur]=0;
if(l==r){
sum[cur]=a[l];
lc[cur]=rc[cur]=0;
return cur;
}
int mid=l+r>>1;
lc[cur]=build(l,mid);
rc[cur]=build(mid+1,r);
pu(cur);
return cur;
}
int update(int old,int l,int r,int L,int R,int v){
int cur=++tot;
delta[cur]=delta[old];
sum[cur]=sum[old];
sum[cur]+=(ll)(min(R,r)-max(L,l)+1)*v;
lc[cur]=lc[old];
rc[cur]=rc[old];
if(L<=l&&r<=R){
delta[cur]+=v;
return cur;
}
int mid=l+r>>1;
if(L<=mid)lc[cur]=update(lc[old],l,mid,L,R,v);
if(R>mid)rc[cur]=update(rc[old],mid+1,r,L,R,v);
//have no pushUp!!!!!!!!!!!
return cur;
}
ll query(int o,int l,int r,int L,int R){
if(L<=l&&r<=R) return sum[o];
int mid=l+r>>1;
ll ans=(ll)(min(r,R)-max(L,l)+1)*delta[o];
if(L<=mid) ans+=query(lc[o],l,mid,L,R);
if(R>mid) ans+=query(rc[o],mid+1,r,L,R);
return ans;
}
}fst;
int main(){
int n,m;
bool flag=0;
while(cin>>n>>m){
if(flag==0) flag=1;
else printf("\n");
rep(i,1,n) a[i]=read();
fst.init();
fst.T[0]=fst.build(1,n);
int now=0;fst.ed[now]=fst.tot;
char str[1<<5];
rep(i,1,m){
scanf("%s",str);
if(str[0]=='C'){
int l=read();
int r=read();
int d=read();
fst.T[now+1]=fst.update(fst.T[now],1,n,l,r,d);
now++; fst.ed[now]=fst.tot;
}else if(str[0]=='Q'){
int l=read();
int r=read();
println(fst.query(fst.T[now],1,n,l,r));
}else if(str[0]=='H'){
int l=read();
int r=read();
int t=read();
println(fst.query(fst.T[t],1,n,l,r));
}else{
int t=read();
now=t;fst.tot=fst.ed[t];
}
}
}
return 0;
}
HDU 2665
静态区间第k大
简单作差主席树即可
#include<bits/stdc++.h>
#include<unordered_map>
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define rrep(i,j,k) for(int i=j;i>=k;i--)
#define erep(i,u) for(int i=head[u];~i;i=nxt[i])
#define print(a) printf("%lld",(ll)(a))
#define printbk(a) printf("%lld ",(ll)(a))
#define println(a) printf("%lld\n",(ll)(a))
using namespace std;
const int MAXN = 1e5+11;
typedef long long ll;
ll read(){
ll x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct FST{
int num[MAXN<<5];
int T[MAXN],tot;
int lc[MAXN<<5],rc[MAXN<<5];
void init(){tot=0;}
void pu(int o){
num[o]=num[lc[o]]+num[rc[o]];
}
int build(int l,int r){
int cur=++tot;
num[cur]=lc[cur]=rc[cur]=0;
if(l==r) return cur;
int mid=l+r>>1;
lc[cur]=build(l,mid);
rc[cur]=build(mid+1,r);
return cur;
}
void copy(int cur,int old){
num[cur]=num[old];
lc[cur]=lc[old];
rc[cur]=rc[old];
}
int update(int old,int l,int r,int k){
int cur=++tot;
copy(cur,old);
if(l==r){
num[cur]++;
return cur;
}
int mid=l+r>>1;
if(k<=mid) lc[cur]=update(lc[old],l,mid,k);
else rc[cur]=update(rc[old],mid+1,r,k);
pu(cur);
return cur;
}
int query(int st,int ed,int l,int r,int k){
while(1){
if(l==r) return l;
int t1=num[lc[ed]]-num[lc[st]];
if(k>t1){
k-=t1;
ed=rc[ed];
st=rc[st];
l=(l+r>>1);l++;
}else{
ed=lc[ed];
st=lc[st];
r=(l+r>>1);
}
}
}
}fst;
int a[MAXN],b[MAXN],c[MAXN];
unordered_map<int,int> mp;
int main(){
int n,m,T=read();
while(T--){
n=read(); m=read(); mp.clear();
rep(i,1,n) b[i]=a[i]=read();
sort(b+1,b+1+n);
int nn=unique(b+1,b+1+n)-b-1;
rep(i,1,n) c[i]=lower_bound(b+1,b+1+nn,a[i])-b;
rep(i,1,n) mp[c[i]]=a[i];
fst.init(); fst.T[0]=fst.build(1,nn);
rep(i,1,n) fst.T[i]=fst.update(fst.T[i-1],1,nn,c[i]);
while(m--){
int st=read();st--;
int ed=read();
int k=read();
println(mp[fst.query(fst.T[st],fst.T[ed],1,nn,k)]);
}
}
return 0;
}
SPOJ - TTM 主席树的更多相关文章
- Count on a tree SPOJ 10628 主席树+LCA(树链剖分实现)(两种存图方式)
Count on a tree SPOJ 10628 主席树+LCA(树链剖分实现)(两种存图方式) 题外话,这是我第40篇随笔,纪念一下.<( ̄︶ ̄)↗[GO!] 题意 是说有棵树,每个节点上 ...
- SPOJ - DQUERY 主席树
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=32356 Given a sequence of n numbers ...
- SPOJ - DQUERY 主席树求区间有多少个不同的数(模板)
D-query Time Limit: 227MS Memory Limit: 1572864KB 64bit IO Format: %lld & %llu Submit Status ...
- D-query SPOJ - DQUERY 主席树查询区间内不同数出现的次数
我们不以权值建立主席树,而是区间端点作为值建立线段树,一个个插入a[i],我们发现这个数之前是存在的,就需要在上个版本的主席树上减去原来的位置,并加上现在的位置,这样我们在i版本的主席树,维护1-r中 ...
- SPOJ - 3267. D-query 主席树求区间个数
SPOJ - 3267 主席树的又一种写法. 从后端点开始添加主席树, 然后如果遇到出现过的元素先把那个点删除, 再更新树, 最后查询区间就好了. #include<bits/stdc++.h& ...
- 2018.08.04 spoj TTM to the moon(主席树)
spoj传送门 vjudge传送门 主席树板子题. 支持历史版本的区间和,区间和,区间修改和时光倒流. 其中新奇一点的也只有区间修改了,这个东西直接标记永久化就行了. 如果想下传标记的话也行,需要在p ...
- BZOJ 2588: Spoj 10628. Count on a tree [树上主席树]
2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MBSubmit: 5217 Solved: 1233 ...
- SPOJ DQUERY D-query(主席树)
题目 Source http://www.spoj.com/problems/DQUERY/en/ Description Given a sequence of n numbers a1, a2, ...
- SPOJ 10628 Count on a tree(Tarjan离线LCA+主席树求树上第K小)
COT - Count on a tree #tree You are given a tree with N nodes.The tree nodes are numbered from 1 to ...
随机推荐
- Python爬虫入门四之Urllib库的高级用法
1.设置Headers 有些网站不会同意程序直接用上面的方式进行访问,如果识别有问题,那么站点根本不会响应,所以为了完全模拟浏览器的工作,我们需要设置一些Headers 的属性. 首先,打开我们的浏览 ...
- 实践作业3:白盒测试----学习Junit框架DAY10.
JUnit - 测试框架 首先应该了解什么是 Junit 测试框架? JUnit 是一个回归测试框架,被开发者用于实施对应用程序的单元测试,加快程序编制速度,同时提高编码的质量.JUnit 测试框架能 ...
- Go 语言并发笔记
前言: 本文是学习<<go语言程序设计>> -- 清华大学出版社(王鹏 编著) 的2014年1月第一版 做的一些笔记 , 如有侵权, 请告知笔者, 将在24小时内删除, 转载请 ...
- MySQL 存储过程 -流程控制的使用
#五.流程控制的使用 #1.IF 使用 create PROCEDURE iftest1() BEGIN DECLARE a int DEFAULT 10; -- IF (a>1 &&a ...
- centos7用fdisk进行分区
1.查看分区信息:fdisk -l 从上面可以看到,/dev/sdb分区还没有使用,现在将其划分成2个10G的分区. 2.执行:fdisk /dev/sdb 1):fdisk命令参数 p:打印分区表. ...
- mybatis 插入实体与数据库中的字段不一致的解决方案
1.建立一个实体类 public class Student { private Integer id; private String name; private Double salary; pub ...
- Redis实现高并发下的抢购、秒杀功能
博主最近在项目中遇到了抢购问题!现在分享下.抢购.秒杀是如今很常见的一个应用场景,主要需要解决的问题有两个:1 高并发对数据库产生的压力2 竞争状态下如何解决库存的正确减少("超卖" ...
- java程序员修炼之前笔记(前半部分)
第一部分 用java7做开发 第一章 初始java7 java7中的新特性 switch支持String 支持100_000_000数值表示法 新的异常处理 | 连接多个异常 final Except ...
- 20169202 2016-2017-2《TCP/IP协议攻击》实验总结--十一周
APR缓存中毒(ARP cache poisoning) 实验原理 ARP缓存是ARP协议的重要组成部分.ARP协议运行的目标就是建立MAC地址和IP地址的映射,然后把这一映射关系保存在ARP缓存中, ...
- hdu2993 MAX Average Problem (斜率dp)
参考:http://www.cnblogs.com/kuangbin/archive/2012/08/27/2657878.html //#pragma warning (disable: 4786) ...