• 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;
    }
    
  • 相关阅读:
    前后端分类状态下SpringSecurity的玩法
    拓展 centos 7
    linux 日志管理
    Linux 内存监控
    Linux 周期任务
    Linux 文件系统
    linux 磁盘管理
    图论 最短路总结
    进阶线段树之乘法操作
    暑假集训Day 10 小烈送菜
  • 原文地址:https://www.cnblogs.com/luyiming123blog/p/P2617.html
Copyright © 2020-2023  润新知