1. 程式人生 > 其它 >BZOJ-2120 數顏色

BZOJ-2120 數顏色

數顏色

帶修莫隊 模板題

看到別人題解,發現有個小技巧,時間緯度在更改的時候直接 swap 當前值和要修改的值,下次回來的時候 swap 回去是一樣的,這樣就可以不用多記錄狀態了

https://fangkaipeng.com/?p=1504

我還發現非常 BZOJ 的資料和 AcWing 的資料相當奇怪,用分塊大小為 \(\sqrt{n}\) 作為分塊會更加快,而洛谷的資料用分塊大小為 \(n^{\frac{2}{3}}\) 會更快

我的猜測是資料範圍約束的問題,BZOJ 和 AcWing 的條件約束說修改的次數在於 1000 次以下,可能就導致了時間緯度修改的比較少,因此最優分塊趨近於 \(\sqrt{n}\)

https://www.acwing.com/problem/content/2523/

正常的複雜度分析來說,分塊大小應該為 \(n^{\frac{2}{3}}\),複雜度為 \(O(n^{\frac{5}{3}})\)

https://www.luogu.com.cn/problem/P1903

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
#define endl '\n'
#define pii pair<int, int>
const int maxn = 133333 + 10;
const ll maxm = 1e6 + 10;
const ll inf = 1e17 + 10;
int num[maxn], pos[maxm], cnt[maxm];
int l = 1, r = 0, ans = 0, t = 0, nn = 0;
int last[maxn];

struct node
{
    int l, r, t, id;
    node(){}
    node(int _l, int _r, int _t, int _id){l = _l; r = _r; t = _t; id = _id;}
}seg[maxn], change[maxn];

bool cmp(const node& a, const node& b)
{
    return pos[a.l] ^ pos[b.l] ? pos[a.l] < pos[b.l] : (pos[a.r] ^ pos[b.r] ? pos[a.r] < pos[b.r] : a.t < b.t);
}

inline void add(int x)
{
    ans += (++cnt[num[x]] == 1);
}

inline void del(int x)
{
    ans -= (--cnt[num[x]] == 0);
}

inline void update(int x)
{
    if(change[x].t >= l && change[x].t <= r)
    {
        del(change[x].t);
        swap(num[change[x].t], change[x].l);
        add(change[x].t);
    }
    else swap(num[change[x].t], change[x].l);
}

int main()
{
    // ios::sync_with_stdio(false);
    // cin.tie(0);
    // cout.tie(0);
    // freopen("text.in", "rb", stdin);
    // freopen("text.out", "wb", stdout);
    int n, m;
    scanf("%d%d", &n, &m);
    int maxx = 0;
    for(int i=1; i<=n; i++) {cin >> num[i]; maxx = num[i] > maxx ? num[i] : maxx;}
    nn = pow(maxn, 2.0 / 3.0);
    for(int i=1; i<=maxx; i++) pos[i] = i / nn;
    int tq = 0, tr = 0;
    for(int i=0; i<m; i++)
    {
        char a;
        int x, y;
        scanf(" %c%d%d", &a, &x, &y);
        if(a == 'Q')
        {
            seg[tq] = node(x, y, tr, tq);
            tq++;
        }
        else
        {
            change[tr] = node(y, 0, x, 0);
            tr++;
        }
    }
    sort(seg, seg + tq, cmp);
    t = 0;

    for(int i=0; i<tq; i++)
    {
        while(t < seg[i].t) update(t++);
        while(t > seg[i].t) update(--t);
        while(r < seg[i].r) add(++r);
        while(l > seg[i].l) add(--l);
        while(r > seg[i].r) del(r--);
        while(l < seg[i].l) del(l++);
        last[seg[i].id] = ans;
    }
    for(int i=0; i<tq; i++)
        printf("%d\n", last[i]);
    return 0;
}