给你一个系列\(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. 【转】The most comprehensive Data Science learning plan for 2017

    I joined Analytics Vidhya as an intern last summer. I had no clue what was in store for me. I had be ...

  2. git post-receive

    1. 将 www 目录设为 777 2. 用git 用户 mkdir 并 git init 3. cat  id_rsa.pub >. authorkeys

  3. git hook 自动部署

    1. 当前虚拟站点根目录的 .git/ 权限 2. 当前项目裸仓库创建 hooks/post-receive 文件,并给予x 的权限 3. 复制如下内容 #!/bin/sh unset $(git r ...

  4. php 导出csv表格文件

    1.数据库取出数据,存放在二维数组中 $conn=new mysqli('localhost','root','root','myDBPDO'); $result=$conn->query('s ...

  5. Smart3d 近景摄影测量与航空摄影测量

    实例:http://blog.sina.com.cn/s/blog_8f68d2350102wef4.html ContextCapture(Smart3d):https://www.bentley. ...

  6. C# 生成dll文件 并导入使用

    首先 在unity创建一个脚本 并编写内容,其中需要调用的方法.变量要公有化(也可以直接新建cs文件用编译器打开编译,但要先导入UnityEngine.dll). 然后,复制脚本关闭unity,在外界 ...

  7. 20160214 2016-2017-2 实验二《Java面向对象》实验报告

    实验二 面向对象程序设计 (一)单元测试 写一段关于分数标准的代码,如下: public class MyUtil{ public static String percentage2fivegrade ...

  8. mysql转ElasticSearch的分析 及JAVA API 初探

    前言 最近工作中在进行一些技术优化,为了减少对数据库的压力,对于只读操作,在程序与db之间加了一层-ElasticSearch.具体实现是db与es通过bin-log进行同步,保证数据一致性,代码调用 ...

  9. 安装pygame for Python3.5

    首先进入pygame官网下载页面:http://www.pygame.org/download.shtml  页面上提供的有py2.4-py2.7,py3.1-py3.2的版本(py2.4就是对应py ...

  10. sonar资料

    看过的sonar比较好的在线参考资料(自认为): 1.<使用 Sonar 进行代码质量管理>>,地址:http://www.ibm.com/developerworks/cn/jav ...