P2617 Dynamic Rankings(动态区间第K小,单点更新) 树状数组套主席树(权值线段树)

题目
Satisfied
题解:与主席树前缀和的思想一致,树状数组维护一个"主席树"(不是前缀和那样的一颗权值线段树 而是low(i)颗权值线段树)
在这里插入图片描述
输入样例#1:
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3

输出样例#1:
3
6

说明

对于所有数据,m,n≤100000
请注意常数优化,但写法正常的整体二分和树套树都可以大约1000ms每个点的时间过。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#define low(a) a&-a
#define m(a,b) memset(a,b,sizof a)
#define en '\n'
using namespace std;
typedef long long ll;
const int N=2e5+5,M=N;
int a[N],refl[N],tot,n,m;
int sum[N*500],root[N],bit1[N],bit2[N],sz;
struct Query{int opt,l,r,k;}q[M];
struct tree{int l,r;}t[N*500];
void update(int &x,int wh,int l,int r,int val)
{
    if(!x)
        x=++sz;
    sum[x]+=val;
    if(l==r)
        return;
    int mid=(l+r)>>1;
    if(wh<=mid)
        update(t[x].l,wh,l,mid,val);
    else
        update(t[x].r,wh,mid+1,r,val);
}
void modify(int pos,int val)
{
    int dex=lower_bound(refl+1,refl+tot+1,a[pos])-refl;
    int i=pos;
    while(i<=n)
    {
        update(root[i],dex,1,tot,val);
        i+=low(i);
    }
}
int query(int o1,int o2,int l,int r,int k)
{
    if(l==r)
        return l;
    int left=0;
    for(int i=1;i<=o1;i++)
        left-=sum[t[bit1[i]].l];
    for(int i=1;i<=o2;i++)
        left+=sum[t[bit2[i]].l];
    int mid=(l+r)>>1;
    if(left>=k)
    {
        for(int i=1;i<=o1;i++)
            bit1[i]=t[bit1[i]].l;
        for(int i=1;i<=o2;i++)
            bit2[i]=t[bit2[i]].l;
        return query(o1,o2,l,mid,k);
    }
    else
    {
        for(int i=1;i<=o1;i++)
            bit1[i]=t[bit1[i]].r;
        for(int i=1;i<=o2;i++)
            bit2[i]=t[bit2[i]].r;
        return query(o1,o2,mid+1,r,k-left);
    }
}
int getans(int l,int r,int k)
{
    int o1=0,o2=0;
    for(int i=l-1;i;i-=low(i))
        bit1[++o1]=root[i];
    for(int i=r;i;i-=low(i))
        bit2[++o2]=root[i];
    return query(o1,o2,1,tot,k);
}
int main()
{
    sz=0;scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]),refl[i]=a[i];
    tot=n;char s[3];
    for(int i=1;i<=m;i++)
    {
        scanf("%s",s);
        if(s[0]=='Q')
            scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k),q[i].opt=1;
        else
            scanf("%d%d",&q[i].l,&q[i].k),q[i].opt=2,refl[++tot]=q[i].k;
    }
    sort(refl+1,refl+tot+1);
    tot=unique(refl+1,refl+tot+1)-(refl+1);
    for(int i=1;i<=n;i++)
        modify(i,1);
    for(int i=1;i<=m;i++)
    {
        if(q[i].opt==1)
            printf("%d\n",refl[getans(q[i].l,q[i].r,q[i].k)]);
        else
        {
            modify(q[i].l,-1);
            a[q[i].l]=q[i].k;
            modify(q[i].l,1);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42576687/article/details/89892686