Dynamic Rankings【LuoGu 2617】【带修改的主席树】【板子】

题目链接

题目大意

n个数,m次操作,操作有修改和查询区间k打值

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

const int N=1e5+5;
int t[N*3],root[N*3],mm,tot,qrr[N*3],qll[N*2],t1,t2,x[N*2],y[N*2],z[N*2],n,m;
struct node
{
    int l,r,sum;
};
node e[N*300];
struct Node{
int l,r,k,flag;
};
Node a[N*2];
char s[5];

int lowbit(int x)
{
    return x&(-x);
}

void update(int &rt,int l,int r,int hs,int v)
{
    if(!rt)
        rt=++tot;
   // e[tot++]=e[rt];
    e[rt].sum+=v;
    if(l==r)
        return ;
    int mid=(l+r)/2;
    if(hs<=mid)
        update(e[rt].l,l,mid,hs,v);
    else
        update(e[rt].r,mid+1,r,hs,v);
}

void add(int i,int v)
{
    z[i]=lower_bound(x+1,x+1+mm,z[i])-x;
    int p=i;
    while(p<=n)
    {
        update(root[p],1,mm,z[i],v);
        p+=lowbit(p);
    }
}

int Sum()
{
    int ans1=0,ans2=0;
    for(int i=1;i<=t1;i++)
        ans1+=e[e[qrr[i]].l].sum;
    for(int i=1;i<=t2;i++)
        ans2+=e[e[qll[i]].l].sum;
    return ans1-ans2;
}

int que(int qr,int ql,int l,int r,int k)
{
    t1=0;t2=0;
    for(int i=qr;i>=1;i-=lowbit(i)) qrr[++t1]=root[i];
    for(int i=ql;i>=1;i-=lowbit(i)) qll[++t2]=root[i];
    while(l<r)
    {
        int ans=Sum();
        int mid=(l+r)/2;
        if(k<=ans)
        {
            for(int i=1;i<=t1;i++)
                qrr[i]=e[qrr[i]].l;
            for(int i=1;i<=t2;i++)
                qll[i]=e[qll[i]].l;
            r=mid;
        }
        else
        {
            for(int i=1;i<=t1;i++)
                qrr[i]=e[qrr[i]].r;
            for(int i=1;i<=t2;i++)
                qll[i]=e[qll[i]].r;
            l=mid+1;
            k-=ans;
        }
    }
    return l;
}

void init()
{
    tot=0;
    memset(root,0,sizeof(root));
    memset(t,0,sizeof(t));
    memset(e,0,sizeof(e));
   // memset(z,0,sizeof(z));
    e[0].sum=e[0].l=e[0].r=0;
}
int main()
{
        //init();
        int ll,rr,kk;
        int cnt=0;
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x[i]);
            y[i]=x[i];
            z[++cnt]=x[i];
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%s",s);
            if(s[0]=='Q')
            {
                scanf("%d %d %d",&ll,&rr,&kk);
                a[i].l=ll;a[i].r=rr;a[i].k=kk;a[i].flag=1;
            }
            else
            {
                scanf("%d %d",&ll,&rr);
                a[i].l=ll;
                a[i].r=rr;
                a[i].flag=0;
                x[++cnt]=rr;z[cnt]=x[cnt];
            }
        }
        sort(x+1,x+1+cnt);
        mm=unique(x+1,x+1+cnt)-x-1;
        for(int i=1;i<=n;i++)
            add(i,1);
        for(int i=1;i<=m;i++)
        {
            if(a[i].flag)
            {
                printf("%d\n",x[que(a[i].r,a[i].l-1,1,mm,a[i].k)]);
            }
            else
            {
                z[a[i].l]=y[a[i].l];
                add(a[i].l,-1);
                z[a[i].l]=a[i].r;
                y[a[i].l]=a[i].r;
                add(a[i].l,1);
            }
        }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值