给你一个系列\(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 主席树的更多相关文章

  1. Count on a tree SPOJ 10628 主席树+LCA(树链剖分实现)(两种存图方式)

    Count on a tree SPOJ 10628 主席树+LCA(树链剖分实现)(两种存图方式) 题外话,这是我第40篇随笔,纪念一下.<( ̄︶ ̄)↗[GO!] 题意 是说有棵树,每个节点上 ...

  2. SPOJ - DQUERY 主席树

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=32356 Given a sequence of n numbers ...

  3. SPOJ - DQUERY 主席树求区间有多少个不同的数(模板)

    D-query Time Limit: 227MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Submit Status ...

  4. D-query SPOJ - DQUERY 主席树查询区间内不同数出现的次数

    我们不以权值建立主席树,而是区间端点作为值建立线段树,一个个插入a[i],我们发现这个数之前是存在的,就需要在上个版本的主席树上减去原来的位置,并加上现在的位置,这样我们在i版本的主席树,维护1-r中 ...

  5. SPOJ - 3267. D-query 主席树求区间个数

    SPOJ - 3267 主席树的又一种写法. 从后端点开始添加主席树, 然后如果遇到出现过的元素先把那个点删除, 再更新树, 最后查询区间就好了. #include<bits/stdc++.h& ...

  6. 2018.08.04 spoj TTM to the moon(主席树)

    spoj传送门 vjudge传送门 主席树板子题. 支持历史版本的区间和,区间和,区间修改和时光倒流. 其中新奇一点的也只有区间修改了,这个东西直接标记永久化就行了. 如果想下传标记的话也行,需要在p ...

  7. 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 ...

  8. SPOJ DQUERY D-query(主席树)

    题目 Source http://www.spoj.com/problems/DQUERY/en/ Description Given a sequence of n numbers a1, a2, ...

  9. 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  ...

随机推荐

  1. maven 执行本地、服务器 jar包安装

    开发时遇到过第三方jar包依赖不了时的尴尬 因为遇到过几次所以记录一下,POM文件引入的个推jar包无效,就必须本地安装了,服务器上的也是一样,执行相同的maven命令就行,注意修改路径!和将jar包 ...

  2. Golang 之 key-value LevelDB

    时常会在应用中用到数据库功能,象 Key-Value 性质的.直接搬个 Redis,Mysql嫌大,好在有 LevelDB,直接编进应用中. 有关什么是 LevelDB 以及 LevelDB 的特性, ...

  3. JavaScript 与JQuery 常用方法比较

    http://drupalchina.cn/content/javascript-yu-jquery-chang-yong-fang-fa-bi-jiao 1.加载DOM区别 JavaScript: ...

  4. bash 环境配置及脚本

    bash是 Bourne Again Shell简称 ,从unix系统的sh发展而来 查看当前shellecho $SHELL查看系统支持的shellcat /etc/shells cd /binls ...

  5. BBS项目之后台管理

    一:后台管理,添加文章样式编写 创建 一个后台管理模板前段页面 <!DOCTYPE html> <html lang="en"> <head> ...

  6. Excel2016通过宏生成拼音码

    一:视图---->宏---->录制宏 二:试图---->宏---->查看宏 三:点击编辑,输入如下代码片段,点击保存,并选择是 Function pinyin(p As Str ...

  7. 编写高质量代码改善C#程序的157个建议——建议126:用名词和名词组给类型命名

    建议126:用名词和名词组给类型命名 类型对应着现实世界中的实际对象.对象在语言中意味着它是一个名词.所以,类型也应该以名词或名词词组去命名. 类型定义了属性和行为.虽然它包含行为,但不是行为本身.所 ...

  8. Head First Python之3文件与异常

    文件基本操作 Python从文本读取数据时,一次会到达一个数据行. sketch.txt文件 Man: Is this the right room for an argument? Other Ma ...

  9. 搭建python+PyQt+Eric平台

    搭建python+PyQt+Eric平台 预备安装程序: 2.1.下载Python3.2 官方网站:http://www.python.org/ 下载地址:http://www.python.org/ ...

  10. Promises讲解

    原生 Promises 是在 ES2015 对 JavaScript 做出最大的改变.它的出现消除了采用 callback 机制的很多潜在问题,并允许我们采用近乎同步的逻辑去写异步代码. 可以说 pr ...