P2617 Dynamic Rankings | 整体二分

题目简述

给一个长度为(n)的序列(a_1,a_2,cdots a_n),有(m)个操作,为以下两种:

  • (x,k) (a_x leftarrow k)
  • (l,r,k) 求区间([l,r])内的第(k)
    (n,m le 10^5).

简单口胡

首先这题毒瘤数据结构是完全可做的。

但是考虑到我可能不会,于是整体二分。

有修改的整体二分其实和无修的差不多,多了一个将原来的改为(-1)的过程。

# include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n,m;
int a[N << 1];

struct node
{
    int l,r,k,type,soc;
    node(){}
    node(int _l,int _r,int _k,int _ty,int _soc) : l(_l),r(_r),k(_k),type(_ty),soc(_soc) {}
}Q[N << 1],q1[N << 1],q2[N << 1];
int tot = 0,qtot = 0,ans[N << 1];

struct BIT
{
    int lowbit(int x) {return x & (-x);}
    int a[N];
    void add(int x,int d) {while(x <= n) {a[x] += d;x += lowbit(x);}}
    int query(int x)
    {
        int ans = 0;
        while(x) {ans += a[x];x -= lowbit(x);}
        return ans;
    }
}T;

template <typename T> void read(T &x)
{
    int w = 1;
    x = 0;
    char ch = getchar();
    while(!isdigit(ch))
    {
        if(ch == '-') w = -1;
        ch = getchar();
    }
    while(isdigit(ch))
    {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    x *= w;
}

template <typename T> void write(T x)
{
    if(x < 0) x = -x;
    if(x >= 10) write(x / 10);
    char ch = (x % 10) + 48;
    putchar(ch);
    return;
}

void qfind(int l,int r,int s,int t)
{
    if(l > r || s > t) return;
    if(l == r)
    {
        for(int i = s; i <= t; i++)
        {
            if(Q[i].type == 2) ans[Q[i].soc] = l;
        }
        return;
    }
    int mid = (l + r) >> 1;
    int cur1 = 0,cur2 = 0;
    for(int i = s; i <= t; i++)
    {
        if(Q[i].type == 1)
        {
            if(Q[i].l <= mid)
            {
                T.add(Q[i].soc,Q[i].k);
                q1[++cur1] = Q[i];
            }
            else q2[++cur2] = Q[i];
        }
        else
        {
            int sum = T.query(Q[i].r) - T.query(Q[i].l - 1);
            if(sum >= Q[i].k) 
            {
                q1[++cur1] = Q[i];
            }
            else
            {
                Q[i].k -= sum;
                q2[++cur2] = Q[i];
            }
        }
    }
    for(int i = 1; i <= cur1; i++) 
    {
        if(q1[i].type == 1) 
        {
            T.add(q1[i].soc,-q1[i].k);
        }
    }
    for(int i = 1; i <= cur1; i++) Q[s + i - 1] = q1[i];
    for(int i = 1; i <= cur2; i++) Q[s + i + cur1 - 1] = q2[i];
    qfind(l,mid,s,s + cur1 - 1);
    qfind(mid + 1,r,s + cur1,t);
    return;
}

int main(void)
{
    read(n),read(m);
    for(int i = 1; i <= n; i++)
    {
        read(a[i]);
        Q[++tot] = node(a[i],0,1,1,i);
    }
    for(int i = 1; i <= m; i++)
    {
        char opt[2];
        scanf("%s",opt);
        int l,r,k;
        if(opt[0] == 'C')
        {
            read(l),read(k);
            Q[++tot] = node(a[l],0,-1,1,l);
            Q[++tot] = node(a[l] = k,0,1,1,l);
        }
        else
        {
            read(l),read(r),read(k);
            Q[++tot] = node(l,r,k,2,++qtot);
        }
    }
    qfind(0,1e9,1,tot);
    for(int i = 1; i <= qtot; i++)
    {
        write(ans[i]);
        putchar('
');
    }
    return 0;
}
原文地址:https://www.cnblogs.com/luyiming123blog/p/P2617.html