给你一个系列\(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. phpmailer配置163邮箱

    function send_email($email = ''){ $this->autoRender = false; date_default_timezone_set('PRC'); re ...

  2. SQL高性能分页

    分页的场景就不多说了,无处不在. 方法一:利用row_number() with C as ( select ROW_NUMBER() over(order by orderdate,orderid) ...

  3. VMware vSphere之vCenter

    1.vCenter是什么? vCenter Server 是 vSphere管理员使用的主要管理工具,首先,通过它可实现对数据中心所有主机的单点控制,也就是提供集中式管理.其次,提供基本的基础结构操作 ...

  4. APUE(4)---文件和目录 (2)

    七.函数umask umask函数为进程设置文件模式创建屏蔽字,并返回之前的值,这是少数几个没有出错返回函数中的一个.其中cmask是9个常量(S_IR/W/XUSR.S_IR/W/XGRP.S_IR ...

  5. LightOJ 1098(均值不等式,整除分块玄学优化)

    We all know that any integer number n is divisible by 1 and n. That is why these two numbers are not ...

  6. Android-Spinner下拉列表

    在布局Layout文件中定义Spinner: <?xml version="1.0" encoding="utf-8"?> <LinearLa ...

  7. Mathcad操作tips:函数、符号计算

    函数 1. 利用“:”进行函数定义,如 2. 函数支持range variable输入,如 3. 常用数学函数可以在Insert - Function菜单中寻得. 4. 当不确定某个名字是否是函数名时 ...

  8. python的requests库详解

    快速上手 迫不及待了吗?本页内容为如何入门 Requests 提供了很好的指引.其假设你已经安装了 Requests.如果还没有,去安装一节看看吧. 首先,确认一下: Requests 已安装 Req ...

  9. asp.net 汉字转拼音类

    前段时间公司人员反应OA里的汉字拼音首字母不准他们又要用,没办法自己就从网上搜有没有好的,看了很多都是首字母拼不出来或有些字母变为另一个,但最后找了很多还是有一个好用的,暂未发现有不准的. using ...

  10. 解决:The APR based Apache Tomcat Native library which allows optimal performance in production...

    tomcat日志apr报错引发的基于Tomcat Native加速Tomcat性能 tomact服务启动报错日志如下:息: The APR based Apache Tomcat Native lib ...