区间第K大:POJ-2104
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=1e5+1000;
int cnt,root[maxn],n,m;
int a[maxn];
vector<int> v;
struct node
{
int l,r,sum;
}tree[maxn*40];
int getid(int x)
{
return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
void insert(int l,int r,int &x,int y,int pos)
{
tree[++cnt]=tree[y];tree[cnt].sum++,x=cnt;
if(l==r) return ;
int m=(l+r)>>1;
if(pos<=m) insert(l,m,tree[x].l,tree[y].l,pos);
else insert(m+1,r,tree[x].r,tree[y].r,pos);
}
int query(int l,int r,int x,int y,int k)
{
if(l==r) return l;
int m=(l+r)>>1;
int sum=tree[tree[y].l].sum-tree[tree[x].l].sum;
if(sum>=k){
return query(l,m,tree[x].l,tree[y].l,k);
}
else return query(m+1,r,tree[x].r,tree[y].r,k-sum);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),v.push_back(a[i]);
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
int sz=v.size();
for(int i=1;i<=n;i++) insert(1,sz,root[i],root[i-1],getid(a[i]));
while(m--)
{
int x,y,k;
scanf("%d%d%d",&x,&y,&k);
printf("%d\n",v[query(1,sz,root[x-1],root[y],k)-1]);
}
return 0;
}
树上第K小:SPOJ-COT
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+1000;
int a[maxn];
struct node
{
int l,r,sum;
}tree[maxn*40];
int cnt,root[maxn];
vector<int> v[maxn],v1;
int num[maxn],fa[maxn][30],depth[maxn];
int n,m,sz;
int getid(int x){
return lower_bound(v1.begin(),v1.end(),x)-v1.begin()+1;
}
//void build(int l,int r,int &rt)
//{
// rt=++cnt;
// tree[rt].sum=0;
// if(l==r) return ;
// int m=(l+r)>>1;
// build(l,m,tree[rt].l);
// build(m+1,r,tree[rt].r);
//}
void update(int l,int r,int &x,int y,int pos){
tree[++cnt]=tree[y];tree[cnt].sum++;x=cnt;
if(l==r) return ;
int m=(l+r)>>1;
if(pos<=m) update(l,m,tree[x].l,tree[y].l,pos);
else update(m+1,r,tree[x].r,tree[y].r,pos);
}
int query(int l,int r,int x,int y,int z,int w,int k){
if(l==r) return l;
int m=(l+r)>>1;
int tmp=tree[tree[x].l].sum+tree[tree[y].l].sum-tree[tree[z].l].sum-tree[tree[w].l].sum;
if(tmp<k){
return query(m+1,r,tree[x].r,tree[y].r,tree[z].r,tree[w].r,k-tmp);
}
else return query(l,m,tree[x].l,tree[y].l,tree[z].l,tree[w].l,k);
}
//lca
void dfs(int u,int pre){
update(1,sz,root[u],root[pre],num[u]);
for(int i=1;(1<<i)<=n;i++) fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=0;i<v[u].size();i++){
int te=v[u][i];
if(te==pre) continue;
depth[te]=depth[u]+1;
fa[te][0]=u;
dfs(te,u);
}
}
int lca(int a,int b){
if(depth[a]>depth[b]) swap(a,b);
int f=depth[b]-depth[a];
for(int j=0;(1<<j)<=f;j++)
{
if(f&(1<<j)) b=fa[b][j];
}
if(a==b) return a;
for(int i=20;i>=0;i--){
if(fa[a][i]!=fa[b][i]){
a=fa[a][i],b=fa[b][i];
}
}
return fa[a][0];
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),v1.push_back(a[i]);
sort(v1.begin(),v1.end());
v1.erase(unique(v1.begin(),v1.end()),v1.end());
for(int i=1;i<n;i++){
int f,t;
scanf("%d%d",&f,&t);
v[f].push_back(t);
v[t].push_back(f);
}
cnt=0;
for(int i=1;i<=n;i++) num[i]=getid(a[i]);
sz=v1.size();
// build(1,sz,root[0]);
dfs(1,0);
while(m--)
{
int x,y,k;
scanf("%d%d%d",&x,&y,&k);
int lc=lca(x,y);
printf("%d\n",v1[query(1,sz,root[x],root[y],root[lc],root[fa[lc][0]],k)-1]);
}
return 0;
}
区间不同值:SPOJ - DQUERY
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+100;
int root[maxn],cnt;
struct node
{
int l,r,num;
}tree[maxn*40];
int a[maxn];
map<int,int> ma;
int sz=maxn;
void insert(int l,int r,int &x,int y,int pos,int v)
{
tree[++cnt]=tree[y];tree[cnt].num+=v;x=cnt;
if(l==r) return ;
int m=(l+r)>>1;
if(pos<=m) insert(l,m,tree[x].l,tree[y].l,pos,v);
else insert(m+1,r,tree[x].r,tree[y].r,pos,v);
}
int query(int l,int r,int L,int R,int y)
{
if(L<=l&&r<=R) return tree[y].num;
int m=(l+r)>>1;
int ans=0;
if(L<=m) ans+=query(l,m,L,R,tree[y].l);
if(R>m) ans+=query(m+1,r,L,R,tree[y].r);
return ans;
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++){
if(ma[a[i]]==0){
insert(1,sz,root[i],root[i-1],i,1);//在第i个位置插入 保证线段树上区间也对应
ma[a[i]]=i;
}
else{
insert(1,sz,root[i],root[i-1],ma[a[i]],-1);
ma[a[i]]=i;
insert(1,sz,root[i],root[i],i,1);
}
}
int m;
cin>>m;
while(m--)
{
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",query(1,sz,x,y,root[y]));//0-root[y]即可
}
return 0;
}
区间第k大+区间不同值:HDU - 5919
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<cmath>
using namespace std;
const int maxn=2e5+1000;
struct node{
int l,r,num;
}tree[maxn*40];
int root[maxn],tot;
int a[maxn];
int sz=maxn;
void update(int l,int r,int &x,int y,int pos,int val)
{
x=++tot;tree[x]=tree[y];tree[x].num+=val;
if(l==r) return ;
int m=(l+r)>>1;
if(pos<=m) update(l,m,tree[x].l,tree[y].l,pos,val);
else update(m+1,r,tree[x].r,tree[y].r,pos,val);
}
int query1(int l,int r,int y,int L,int R)
{
if(L<=l&&r<=R)
{
return tree[y].num;
}
int m=(l+r)>>1;
int ans=0;
if(L<=m) ans+=query1(l,m,tree[y].l,L,R);
if(R>m) ans+=query1(m+1,r,tree[y].r,L,R);
return ans;
}
int query2(int l,int r,int y,int k)
{
if(l==r) return l;
int m=(l+r)>>1;
int tmp=tree[tree[y].l].num;
if(k>tmp) return query2(m+1,r,tree[y].r,k-tmp);
else return query2(l,m,tree[y].l,k);
}
int main()
{
int kase;
scanf("%d",&kase);
int cc=0;
while(kase--)
{
int lastans=0;
tot=0;
memset(root,0,sizeof(root));
memset(tree,0,sizeof(tree));
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
map<int,int> ma;
for(int i=n;i>=1;i--)
{
if(ma[a[i]]==0){
update(1,sz,root[i],root[i+1],i,1);
}else{
update(1,sz,root[i],root[i+1],ma[a[i]],-1);
update(1,sz,root[i],root[i],i,1);
}
ma[a[i]]=i;
}
printf("Case #%d: ",++cc);
while(m--)
{
int l,r;
scanf("%d%d",&l,&r);
int ll=l;
l=min((l+lastans)%n+1,(r+lastans)%n+1);
r=max((ll+lastans)%n+1,(r+lastans)%n+1);
int k=query1(1,sz,root[l],l,r);
lastans=query2(1,sz,root[l],ceil(1.0*k/2));
printf("%d",lastans);
if(m==0) puts("");
else printf(" ");
}
}
return 0;
}
主席树区间更新:HDU - 4348
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e5+1000;
typedef long long ll;
int a[maxn];
struct node
{
int l,r;
ll sum,lazy;
}tree[maxn*40];
int root[maxn],tot;
int n,m;
int sz=maxn;
void build(int l,int r,int &x)
{
x=++tot;
tree[x].sum=0;
tree[x].lazy=0;
if(l==r)
{
tree[x].sum+=a[l];
return ;
}
int m=(l+r)>>1;
build(l,m,tree[x].l);
build(m+1,r,tree[x].r);
tree[x].sum=tree[tree[x].l].sum+tree[tree[x].r].sum;
}
void update(int l,int r,int L,int R,int &x,int y,int val)
{
x=++tot;
tree[x]=tree[y];
tree[x].sum+=1ll*val*(min(R,r)-max(l,L)+1);
if(L<=l&&r<=R){
tree[x].lazy+=val;
return ;
}
int m=(l+r)>>1;
if(L<=m) update(l,m,L,R,tree[x].l,tree[y].l,val);
if(R>m) update(m+1,r,L,R,tree[x].r,tree[y].r,val);
}
ll query(int l,int r,int L,int R,int x,ll lazy)
{
if(L<=l&&r<=R){
return tree[x].sum+lazy*(r-l+1);
}
ll ans=0;
int m=(l+r)>>1;
if(L<=m) ans+=query(l,m,L,R,tree[x].l,lazy+tree[x].lazy);
if(R>m) ans+=query(m+1,r,L,R,tree[x].r,lazy+tree[x].lazy);
return ans;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
tot=0;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
int p=0;
build(1,sz,root[p]);
while(m--)
{
char op[10];
scanf("%s",op);
if(op[0]=='Q'){
int l,r;
scanf("%d%d",&l,&r);
printf("%lld\n",query(1,sz,l,r,root[p],0));
}
else if(op[0]=='C'){
int l,r,d;
scanf("%d%d%d",&l,&r,&d);
update(1,sz,l,r,root[p+1],root[p],d);
p++;
}
else if(op[0]=='B'){
int t;
scanf("%d",&t);
p=t;
}
else if(op[0]=='H'){
int l,r,t;
scanf("%d%d%d",&l,&r,&t);
printf("%lld\n",query(1,sz,l,r,root[t],0));
}
}
}
return 0;
}