ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Template - 「整体二分」

2022-02-16 22:00:21  阅读:175  来源: 互联网

标签:二分 Node return int void 整体 char MAXN Template


写的简单。主要是留给自己做复习资料。


Dynamic Rankings.

给定一个含有 \(n\) 个数的序列 \(a_1,a_2 \dots a_n\),需要支持两种操作:

  • Q l r k 表示查询下标在区间 \([l,r]\) 中的第 \(k\) 小的数。
  • C x y 表示将 \(a_x\) 改为 \(y\)。

引入整体二分。

其实就是我们对于二分到的一个值域 mid,去离线针对所有的询问进行 check。

具体是利用一些数据结构。

然后根据 check 和 mid 的大小将询问分为两拨,再分治下去解决问题。

参考于 OI-wiki 的板子很精简且思路便于理解。

#include <cstdio>

int Abs (int x) { return x < 0 ? -x : x; }
int Max (int x, int y) { return x > y ? x : y; }
int Min (int x, int y) { return x < y ? x : y; }

int Read () {
    int x = 0, k = 1;
    char s = getchar();
    while (s < '0' || s > '9') {
        if(s == '-')
            k = -1;
        s = getchar ();
    } 
    while ('0' <= s && s <= '9') 
        x = (x << 3) + (x << 1) + (s ^ 48), s = getchar ();
    return x * k;
}

void Write (int x) {
    if(x < 0) 
        x = -x, putchar ('-');
    if(x > 9)
        Write (x / 10);
    putchar (x % 10 + '0');
}

void Print (int x, char s) { Write (x), putchar (s); }

const int MAXN = 2e5 + 5;

char Opt[3];
int Ans[MAXN], BIT[MAXN], a[MAXN], n, m;

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

void Update (int k, int x) {
    for (int i = k; i <= n; i += Low_Bit (i))
        BIT[i] += x;
}

int Query (int k) {
    int Res = 0;
    for (int i = k; i >= 1; i -= Low_Bit (i))
        Res += BIT[i];
    return Res;
}

struct Node {
    bool Type;
    int Id, x, y, k;
    Node () {}
    Node (bool T, int I, int X, int Y, int K) {
        Type = T, Id = I, x = X, y = Y, k = K;
    }
} q[MAXN], Tmp[2][MAXN];

void Solve (int l, int r, int L, int R) {
    if (l > r || L > R)
        return ;
    if (L == R) {
        for (int i = l; i <= r; i++)
            if (q[i].Type)
                Ans[q[i].Id] = L;
        return ;
    }
    // printf ("%d %d %d %d : //\n", l, r, L, R);
    // for (int i = l; i <= r; i++)
    //     printf ("%d %d %d %d %d\n", q[i].Type, q[i].Id, q[i].x, q[i].y, q[i].k);
    // printf ("//\n");
    int Mid = (L + R) >> 1, Cnt0 = 0, Cnt1 = 0;
    for (int i = l; i <= r; i++) 
        if (q[i].Type) {
            int Check = Query (q[i].y) - Query (q[i].x - 1);
            if (q[i].k <= Check)
                Tmp[0][++Cnt0] = q[i];
            else 
                q[i].k -= Check, Tmp[1][++Cnt1] = q[i];
        }
        else {
            if (q[i].y <= Mid)
                Update (q[i].x, q[i].k), Tmp[0][++Cnt0] = q[i];
            else 
                Tmp[1][++Cnt1] = q[i];
        }
    for (int i = 1; i <= Cnt0; i++)
        if (!Tmp[0][i].Type)
            Update (Tmp[0][i].x, -Tmp[0][i].k);
    for (int i = 1; i <= Cnt0; i++)
        q[l + i - 1] = Tmp[0][i];
    for (int i = 1; i <= Cnt1; i++)
        q[l + Cnt0 + i - 1] = Tmp[1][i];
    Solve (l, l + Cnt0 - 1, L, Mid), Solve (l + Cnt0, r, Mid + 1, R);
}

int main () {
    n = Read (), m = Read ();
    int p = 0, Tot = 0;
    for (int i = 1, x; i <= n; i++)
        x = Read (), q[++p] = Node (0, 0, i, x, 1), a[i] = x;
    for (int i = 1, x, y; i <= m; i++) {
        scanf ("%s", Opt + 1), x = Read (), y = Read ();
        if (Opt[1] == 'Q') {
            int k = Read ();
            q[++p] = Node (1, ++Tot, x, y, k);
        }
        else 
            q[++p] = Node (0, 0, x, a[x], -1), q[++p] = Node (0, 0, x, y, 1), a[x] = y;
    }
    Solve (1, p, 0, 1e9);
    for (int i = 1; i <= Tot; i++)
        Print (Ans[i], '\n');
    return 0;
}

标签:二分,Node,return,int,void,整体,char,MAXN,Template
来源: https://www.cnblogs.com/LoveMiffyForever/p/15902483.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有