1.静态区间第k小
题解思路
对于每个位置维护一个线段树,显然每个线段树维护的信息可以加减
所以通过类似前缀和的思想求区间第k小
代码
#include <cstdio>
#include <algorithm>
#define ci const int
#define mid ((l+r)>>1)
ci Maxn=200010;
int n,m,N,l,r,k;
int a[Maxn],b[Maxn],T[Maxn];
struct Node {
int cnt;
int s[Maxn<<5],ls[Maxn<<5],rs[Maxn<<5];
int build(ci& l,ci& r) {
int rt=++cnt;
if (l^r) ls[rt]=build(l,mid),rs[rt]=build(mid+1,r);
return rt;
}
int modify(ci& pre,ci& l,ci& r,ci& x) {
int rt=++cnt;
s[rt]=s[pre]+1;ls[rt]=ls[pre];rs[rt]=rs[pre];
if (l^r) x<=mid?ls[rt]=modify(ls[pre],l,mid,x):rs[rt]=modify(rs[pre],mid+1,r,x);
return rt;
}
int query(ci& L,ci& R,ci& l,ci& r,ci& k) {
if (l==r) return l;
int xx=s[ls[R]]-s[ls[L]];
return k<=xx?query(ls[L],ls[R],l,mid,k):query(rs[L],rs[R],mid+1,r,k-xx);
}
}sgt;
int main() {
scanf("%d%d",&n,&m);
for (register int i=1;i<=n;++i) scanf("%d",&a[i]),b[i]=a[i];
std::sort(b+1,b+n+1); N=std::unique(b+1,b+n+1)-b-1;
T[0]=sgt.build(1,N);
for (register int i=1;i<=n;++i) T[i]=sgt.modify(T[i-1],1,N,std::lower_bound(b+1,b+N+1,a[i])-b);
for (register int i=1;i<=m;++i) {
scanf("%d%d%d",&l,&r,&k);
printf("%d
",b[sgt.query(T[l-1],T[r],1,N,k)]);
}
}
2.可持久化数组
题意简述
维护一个数组,支持查询或修改某一历史版本某一位置的值
代码
#include <cstdio>
#include <algorithm>
#define ci const int
#define mid ((l+r)>>1)
ci Maxn=1000010;
int n,m,pre,opt,loc,val;
int a[Maxn],T[Maxn];
struct Node {
int cnt;
int va[Maxn<<4],ls[Maxn<<4],rs[Maxn<<4];
int build(ci& l,ci& r) {
int rt=++cnt;
if (l^r) ls[rt]=build(l,mid),rs[rt]=build(mid+1,r);
else va[rt]=a[l];
return rt;
}
int modify(ci& pre,ci& l,ci& r) {
int rt=++cnt;
va[rt]=va[pre];ls[rt]=ls[pre];rs[rt]=rs[pre];
if (l^r) loc<=mid?ls[rt]=modify(ls[pre],l,mid):rs[rt]=modify(rs[pre],mid+1,r);
else va[rt]=val;
return rt;
}
int query(ci& edt,ci& l,ci& r) {
if (l==r) return va[edt];
return loc<=mid?query(ls[edt],l,mid):query(rs[edt],mid+1,r);
}
}sgt;
int main() {
scanf("%d%d",&n,&m);
for (register int i=1;i<=n;++i) scanf("%d",&a[i]);
T[0]=sgt.build(1,n);
for (register int i=1;i<=m;++i) {
scanf("%d%d%d",&pre,&opt,&loc);
if (opt==1) scanf("%d",&val),T[i]=sgt.modify(T[pre],1,n);
else printf("%d
",sgt.query(T[pre],1,n)),T[i]=T[pre];
}
}