比树套树不知道好写到哪里去了
区间kth poj2104
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define mid ((l+r)>>1)
#define MAXN (100000*100)
#define N 100000
using namespace std;
inline int read()
{
int x=0,f=1;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 n,m,cnt=0,a[N+5],b[N+5];
int root[MAXN],ls[MAXN],rs[MAXN],s[MAXN];
void build(int &rt,int l,int r)
{
rt=++cnt;
if(l==r) return;
build(ls[rt],l,mid);
build(rs[rt],mid+1,r);
}
void pushup(int cnt){s[cnt]=s[ls[cnt]]+s[rs[cnt]];}
void update(int pre,int &rt,int l,int r,int v)
{
rt=++cnt;
if(l==r){s[rt]++;return;}
if(v<=mid) rs[rt]=rs[pre],update(ls[pre],ls[rt],l,mid,v);
else ls[rt]=ls[pre],update(rs[pre],rs[rt],mid+1,r,v);
pushup(rt);
}
int query(int lcnt,int rcnt,int l,int r,int k)
{
if(l==r) return l;
int sum=s[ls[rcnt]]-s[ls[lcnt]];
if(k<=sum) return query(ls[lcnt],ls[rcnt],l,mid,k);
else return query(rs[lcnt],rs[rcnt],mid+1,r,k-sum);
}
void init()
{
for(int i=1;i<=n;i++) b[i]=a[i];
sort(b+1,b+1+n);
for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+1+n,a[i])-b;
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++) a[i]=read();
build(root[0],0,N),init();
for(int i=1;i<=n;i++) update(root[i-1],root[i],0,N,a[i]);
while(m--)
{
int l=read(),r=read(),k=read();
printf("%d\n",b[query(root[l-1],root[r],0,N,k)]);
}
return 0;
}
区间修改(标记永久化) & 历史版本询问 hdu4348
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#define N 100005
#define MAXN (100005*50)
#define mid ((l+r)>>1)
#define LL long long
using namespace std;
int n,m,cnt=0,a[N],T=0;
int root[N+5],ls[MAXN],rs[MAXN];
LL s[MAXN],add[MAXN];
void build(int &rt,int l,int r)
{
rt=++cnt;
if(l==r){s[rt]=a[l];return;}
build(ls[rt],l,mid);
build(rs[rt],mid+1,r);
s[rt]=s[ls[rt]]+s[rs[rt]];
}
void update(int pre,int &rt,int l,int r,int nl,int nr,LL v)
{
rt=++cnt;
s[rt]=s[pre]+(LL)(nr-nl+1)*v;
add[rt]=add[pre];//!!继承标记
if(l==nl&&r==nr)
{
ls[rt]=ls[pre];
rs[rt]=rs[pre];
add[rt]+=v;
return;
}
if(nl>mid) ls[rt]=ls[pre],update(rs[pre],rs[rt],mid+1,r,nl,nr,v);
else if(nr<=mid) rs[rt]=rs[pre],update(ls[pre],ls[rt],l,mid,nl,nr,v);
else update(ls[pre],ls[rt],l,mid,nl,mid,v),update(rs[pre],rs[rt],mid+1,r,mid+1,nr,v);
}
LL query(int rt,int l,int r,int nl,int nr)
{
if(l==nl&&r==nr) return s[rt];
LL tmp=(LL)add[rt]*(nr-nl+1);
if(nl>mid) return query(rs[rt],mid+1,r,nl,nr)+tmp;
else if(nr<=mid) return query(ls[rt],l,mid,nl,nr)+tmp;
else return query(ls[rt],l,mid,nl,mid)+query(rs[rt],mid+1,r,mid+1,nr)+tmp;
}
void init()
{
cnt=T=0;
memset(root,0,sizeof(root));
memset(ls,0,sizeof(ls));
memset(rs,0,sizeof(rs));
memset(add,0,sizeof(add));
memset(s,0,sizeof(s));
}
int main()
{
bool f=1;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(f) f=0;
else printf("\n"),init();
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
build(root[0],1,n);
while(m--)
{
char t[5]; scanf("%s",t);
if(t[0]=='C')
{
T++;
int l,r,v; scanf("%d%d%d",&l,&r,&v);
update(root[T-1],root[T],1,n,l,r,v);
}
else if(t[0]=='B') scanf("%d",&T);
else
{
int l,r,h; scanf("%d%d",&l,&r);
if(t[0]=='Q') printf("%lld\n",query(root[T],1,n,l,r));
else if(t[0]=='H') scanf("%d",&h),printf("%lld\n",query(root[h],1,n,l,r));
}
}
}
return 0;
}
树上kth 差分一下即可
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#define N 100000
#define MAXN (100000*50)
#define mid ((l+r)>>1)
using namespace std;
inline int read()
{
int x=0,f=1;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 n,m,cnt,num;
int pre[N+5],deep[N+5],f[N+5][21],a[N+5],b[N+5];
int s[MAXN],root[N+5],rs[MAXN],ls[MAXN];
struct edge{int to,next;}e[MAXN];
void addedge(int a,int b)
{
num++;
e[num].to=b;
e[num].next=pre[a];
pre[a]=num;
}
void init()
{
for(int k=1;k<=20;k++)
for(int i=1;i<=n;i++)
if(f[i][k-1]) f[i][k]=f[f[i][k-1]][k-1];
}
int get_lca(int u,int v)
{
if(deep[u]<deep[v]) swap(u,v);
int t=(int)log2(deep[u]);
for(int i=t;i>=0;i--)
if(deep[f[u][i]]>=deep[v]) u=f[u][i];
if(u==v) return u;
for(int i=t;i>=0;i--)
if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i];
return f[u][0];
}
void update(int pre,int &rt,int l,int r,int v)
{
rt=++cnt;
if(l==r){s[rt]=s[pre]+1;return;}
if(v<=mid) rs[rt]=rs[pre],update(ls[pre],ls[rt],l,mid,v);
else ls[rt]=ls[pre],update(rs[pre],rs[rt],mid+1,r,v);
s[rt]=s[ls[rt]]+s[rs[rt]];
}
void dfs(int u,int fa,int h)
{
f[u][0]=fa,deep[u]=h;
update(root[fa],root[u],1,N,a[u]);
for(int i=pre[u];i;i=e[i].next)
{
int v=e[i].to;
if(v==fa) continue;
dfs(v,u,h+1);
}
}
int query(int u,int v,int lca,int fa,int l,int r,int k)
{
if(l==r) return l;
int tmp=s[ls[u]]+s[ls[v]]-s[ls[lca]]-s[ls[fa]];
if(k<=tmp) return query(ls[u],ls[v],ls[lca],ls[fa],l,mid,k);
else return query(rs[u],rs[v],rs[lca],rs[fa],mid+1,r,k-tmp);
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++)
b[i]=a[i]=read();
for(int i=1;i<n;i++)
{
int a=read(),b=read();
addedge(a,b),addedge(b,a);
}
sort(b+1,b+1+n);
for(int i=1;i<=n;i++)
a[i]=lower_bound(b+1,b+1+n,a[i])-b;
dfs(1,0,1);
init();
for(int i=1,ans=0;i<=m;i++)
{
int u=read()^ans,v=read(),k=read(),lca=get_lca(u,v);
if(i!=m) printf("%d\n",ans=b[query(root[u],root[v],root[lca],root[f[lca][0]],1,N,k)]);
else printf("%d",ans=b[query(root[u],root[v],root[lca],root[f[lca][0]],1,N,k)]);
}
return 0;
}