动态主席树

一般需要离散化

无离散化模板

const int MAX_N=100100;
int n,m,num=0,len;
int a[MAX_N];
int root[MAX_N],root1[MAX_N],lc[MAX_N],rc[MAX_N],lcnt,rcnt,nn;
struct skt{
 int l,r,sum;
}f[MAX_N*400];
void locate(int l,int r){
 lcnt=0;rcnt=0;
 while(l){
  lc[++lcnt]=root1[l];
  l-=(l&-l);
 }
 while(r){
  rc[++rcnt]=root1[r];
  r-=(r&-r);
 }
}
void add(int k,int k1,int l,int r,int x,int val){
 if(l==r){
        f[k1].sum=f[k].sum;
  f[k1].sum+=val;
  return;
 }
 int mid=(l+r)>>1;
 if(x<=mid){
  f[k1].l=++num;
  f[k1].r=f[k].r;
  add(f[k].l,f[k1].l,l,mid,x,val);
 }
 else{
        f[k1].l=f[k].l;
        f[k1].r=++num;
        add(f[k].r,f[k1].r,mid+1,r,x,val);
 }
 f[k1].sum=f[f[k1].l].sum+f[f[k1].r].sum;
}
void change(int p,int x,int y){
 while(p<=n){
  int ca=root1[p];
  root1[p]=++num;
  add(ca,root1[p],1,len,x,-1);
  ca=root1[p];
  root1[p]=++num;
  add(ca,root1[p],1,len,y,1);
        p+=(p&-p);
 }
}
int ask(int k,int k1,int l,int r,int x){
    int i;
 if(l==r)
    return l;
 int mid=(l+r)>>1;
 int ans=0;
 for(i=1;i<=lcnt;i++){
        ans-=f[f[lc[i]].l].sum;
 }
 for(i=1;i<=rcnt;i++){
        ans+=f[f[rc[i]].l].sum;
 }
 ans+=f[f[k1].l].sum-f[f[k].l].sum;
 if(ans>=x){
  for(i=1;i<=lcnt;i++)
  lc[i]=f[lc[i]].l;
  for(i=1;i<=rcnt;i++)
  rc[i]=f[rc[i]].l;
  return ask(f[k].l,f[k1].l,l,mid,x);
 }
 else{
  for(i=1;i<=lcnt;i++)
  lc[i]=f[lc[i]].r;
  for(i=1;i<=rcnt;i++)
  rc[i]=f[rc[i]].r;
  return ask(f[k].r,f[k1].r,mid+1,r,x-ans);
 }
}

用法

    for(i=0;i<m;i++){
        scanf("%d",&op);
        if(op==0){//修改
            scanf("%d%d",&x,&y);
         int ca=a[x];
         a[x]=y;
         change(x,ca,y);
  }
  else{//查询
      scanf("%d%d%d",&x,&y,&k);
   locate(x-1,y);
   printf("%d\n",ans[ask(root[x-1],root[y],1,len,k)]);
  }
    }

动态主席树 模板题

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAX_N=100100;
int n,m,num=0,len;
int a[MAX_N],b[MAX_N],sub_a[MAX_N<<1],ans[MAX_N<<1];
int root[MAX_N],root1[MAX_N],lc[MAX_N],rc[MAX_N],lcnt,rcnt,nn;
struct skt{
 int l,r,sum;
}f[MAX_N*400];
void locate(int l,int r){
 lcnt=0;rcnt=0;
 while(l){
  lc[++lcnt]=root1[l];
  l-=(l&-l);
 }
 while(r){
  rc[++rcnt]=root1[r];
  r-=(r&-r);
 }
}
void add(int k,int k1,int l,int r,int x,int val){
 if(l==r){
        f[k1].sum=f[k].sum;
  f[k1].sum+=val;
  return;
 }
 int mid=(l+r)>>1;
 if(x<=mid){
  f[k1].l=++num;
  f[k1].r=f[k].r;
  add(f[k].l,f[k1].l,l,mid,x,val);
 }
 else{
        f[k1].l=f[k].l;
        f[k1].r=++num;
        add(f[k].r,f[k1].r,mid+1,r,x,val);
 }
 f[k1].sum=f[f[k1].l].sum+f[f[k1].r].sum;
}
void change(int p,int x,int y){
 while(p<=n){
  int ca=root1[p];
  root1[p]=++num;
  add(ca,root1[p],1,len,x,-1);
  ca=root1[p];
  root1[p]=++num;
  add(ca,root1[p],1,len,y,1);
        p+=(p&-p);
 }
}
int ask(int k,int k1,int l,int r,int x){
    int i;
 if(l==r)
    return l;
 int mid=(l+r)>>1;
 int ans=0;
 for(i=1;i<=lcnt;i++){
        ans-=f[f[lc[i]].l].sum;
 }
 for(i=1;i<=rcnt;i++){
        ans+=f[f[rc[i]].l].sum;
 }
 ans+=f[f[k1].l].sum-f[f[k].l].sum;
 if(ans>=x){
  for(i=1;i<=lcnt;i++)
  lc[i]=f[lc[i]].l;
  for(i=1;i<=rcnt;i++)
  rc[i]=f[rc[i]].l;
  return ask(f[k].l,f[k1].l,l,mid,x);
 }
 else{
  for(i=1;i<=lcnt;i++)
  lc[i]=f[lc[i]].r;
  for(i=1;i<=rcnt;i++)
  rc[i]=f[rc[i]].r;
  return ask(f[k].r,f[k1].r,mid+1,r,x-ans);
 }
}
struct node{
 int op,x,y,k;
}que[MAX_N];
int main(void){
    int i;
 scanf("%d%d",&n,&m);
 for(i=1;i<=n;i++){
  scanf("%d",&a[i]);
  sub_a[i-1]=a[i];
 }
 string s;
 int cntt=n;
 for(i=0;i<m;i++){
  cin>>s;
  if(s[0]=='Q')
  que[i].op=1;
  else
  que[i].op=0;
  if(que[i].op==1){
   scanf("%d%d%d",&que[i].x,&que[i].y,&que[i].k);
  }
  else{
   scanf("%d%d",&que[i].x,&que[i].y);
   sub_a[cntt]=que[i].y;
   cntt++;
  }
 }
 sort(sub_a,sub_a+cntt);
 int nn=unique(sub_a,sub_a+cntt)-sub_a;
 for(i=1;i<=n;i++){
  b[i]=lower_bound(sub_a,sub_a+nn,a[i])-sub_a+1;
  ans[b[i]]=a[i];
 }
 len=nn;
  for(i=1;i<=n;i++){
        root[i]=++num;
        add(root[i-1],root[i],1,len,b[i],1);
    }
    int cnt=n;
    for(i=0;i<m;i++){
        if(que[i].op==0){
         cnt++;
         int ca=b[que[i].x];
         b[que[i].x]=lower_bound(sub_a,sub_a+nn,que[i].y)-sub_a+1;
         ans[b[que[i].x]]=que[i].y;
         change(que[i].x,ca,b[que[i].x]);
  }
  else{
   locate(que[i].x-1,que[i].y);
   printf("%d\n",ans[ask(root[que[i].x-1],root[que[i].y],1,len,que[i].k)]);
  }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值