给你一个系列\(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. [Fiddler] 在 Composer 中对HTTP报文进行编辑,重新执行

    如果想要对某个HTTP请求进行编辑,然后重新执行观察结果,可以将这个报文从左侧拖放到右侧的Composer里面 这样就可以很方便的修改HTTP请求的方法,报文头,报文体 在用 SoapUI 做 API ...

  2. Mysql加载本地CSV文件

    Mysql加载本地CSV文件 1.系统环境 系统版本:Win10 64位 Mysql版本: 8.0.15 MySQL Community Server - GPL Mysql Workbench版本: ...

  3. Flask框架 之 第三方组件

    浏览目录 flask-session flask-sqlalchemy flask-script flask-migrate flask-session 安装 pip3 install flask-s ...

  4. TF Boys (TensorFlow Boys ) 养成记(一):TensorFlow 基本操作

    本资料是在Ubuntu14.0.4版本下进行,用来进行图像处理,所以只介绍关于图像处理部分的内容,并且默认TensorFlow已经配置好,如果没有配置好,请参考官方文档配置安装,推荐用pip安装.关于 ...

  5. [GO]接口的嵌用继承

    package main import "fmt" type Humaner interface { SayHi() } type Personer interface { Hum ...

  6. Introducing .NET Standard

    https://blogs.msdn.microsoft.com/dotnet/2016/10/18/the-week-in-net-bond-the-gallery/ .NET Standard s ...

  7. 回归(regression)、梯度下降(gradient descent)

    本文由LeftNotEasy所有,发布于http://leftnoteasy.cnblogs.com.如果转载,请注明出处,在未经作者同意下将本文用于商业用途,将追究其法律责任. 前言: 上次写过一篇 ...

  8. .NET基础 (01).NET基础概念

    .NET基础概念 1 什么是CTS.CLS和CLR2 开发和运行.NET程序需要的最基本环节是什么3 .NET是否支持多编程语言开发4 CLR技术和COM技术的比较5 什么是程序集和应用程序域 1 什 ...

  9. mysql多字段唯一索引

    项目中需要用到联合唯一索引: 例如:有以下需求:每个人每一天只有可能产生一条记录:处了程序约定之外,数据库本身也可以设定: 例如:user表中有userID,userName两个字段,如果不希望有2条 ...

  10. Python之模块一

    1 >模块介绍: 模块,用一坨代码实现了某个功能的代码集合,类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的          重用性和代码间的吻合, ...