ZOJ - 2112 带修改区间第k小 (分块)

Dynamic Rankings

 ZOJ - 2112 

解题思路:和求区间内小于等于某个数得个数的做一样。不一样的只是这个值需要我们去二分找。

虽然时间上不太优秀,但是代码量小了很多,比树套树好写一点,思想也比较简单。

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<set>
#include<cmath>
#include<map>
#include<algorithm>
#include<cstring>
using namespace std;
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define sca(x) scanf("%d",&x)
#define pb(x) push_back(x)
#define per(i,j,k) for(int i=j;i>=k;i--)
#define inf 0x3f3f3f3f
#define LL long long
#define N 50005
#define inf 0x3f3f3f3f

int len;
int a[N],b[N];
vector<int>v[255];
void init(int n)
{
    rep(i,1,255)v[i].clear();
    rep(i,1,n)sca(a[i]);
    rep(i,1,n)b[i]=(i-1)/len+1;
    rep(i,1,n)v[b[i]].pb(a[i]);
    rep(i,1,b[n])sort(v[i].begin(),v[i].end());
}

void reset(int x)
{
    int now=b[x];
    v[now].clear();
    for(int i=(now-1)*len+1;i<=now*len;i++)v[now].pb(a[i]);
    sort(v[now].begin(),v[now].end());
}

void modify(int x,int y)
{
    a[x]=y;
    reset(x);
}

int query(int l,int r,int k)
{
    int ans=0;
    for(int i=l;i<=min(b[l]*len,r);i++)if(a[i]<=k)ans++;
    if(b[l]!=b[r])
    {
        for(int i=(b[r]-1)*len+1;i<=r;i++)if(a[i]<=k)ans++;
    }
    rep(i,b[l]+1,b[r]-1)
    {
        int pos=upper_bound(v[i].begin(),v[i].end(),k)-v[i].begin();
        ans+=pos;
    }
    return ans;
}

void work(int m)
{
    while(m--)
    {
        char s[3];
        int x,y,k;
        scanf("%s",s);
        if(s[0]=='Q')
        {
            scanf("%d%d%d",&x,&y,&k);
            int l=1,r=1e9;
            int ans;
            while(l<r)
            {
                int m=(l+r)>>1;
                if(query(x,y,m)>=k)r=m;
                else  l=m+1;
            }
            printf("%d\n",r);
        }
        else
        {
            scanf("%d%d",&x,&y);
            modify(x,y);
        }
    }
}
int main()
{
    int t;
    sca(t);
    while(t--)
    {
        int n,m;
        len=sqrt(n);
        sca(n),sca(m);
        init(n);
        work(m);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_40894017/article/details/83096353