c++ 算法题-美团-小美的彩带

这个题脱胎于洛谷的P1972 [SDOI2009] HH的项链

#include<bits/stdc++.h>

using namespace std;

struct Q {
    int i, l, r;
};

bool cmp(const Q &a, const Q &b) {
    return a.r < b.r;
}

class BIT {
public:
    vector<int> bits;

    BIT(int n) : bits(n + 10) {}

    void add(int i, int v) {
        i++;
        while (i < bits.size()) {
            bits[i] += v;
            i += (i & -i);
        }
    }

    int sum(int i) {
        i++;
        int res = 0;
        while (i) {
            res += bits[i];
            i &= (i - 1);
        }
        return res;
    }

    int query(int l, int r) {
        return sum(r) - sum(l - 1);
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, q;
    cin >> n >> q;
    vector<int> a(n * 2);
    for (int i = 0; i < n; i++) cin >> a[i];
    for (int i = 0; i < n; i++) {
        a[i + n] = a[i];
    }
    int All = 0;
    {
        unordered_map<int, int> cnt;
        for (int i = 0; i < n; i++) {
            cnt[a[i]]++;
        }
        All = cnt.size();
    }
    vector<Q> pre, post;
    vector<long long> ans(q);
    long long li = 0, ri = 0;
    for (int i = 0; i < q; i++) {
        char c;
        int x;
        cin >> c >> x;
        if (c == 'L') {
            if (x >= n) {
                ans[i] = All;
            } else {
                int px = li % n;
                int py = (li + x - 1) % n;
                if (py < px) py += n;
                pre.push_back({i, px, py});
            }
            li += x;
        } else {
            if (x >= n) {
                ans[i] = All;
            } else {
                int px = ri % n;
                int py = (ri + x - 1) % n;
                if (py < px) py += n;

                post.push_back({i, px, py});
            }
            ri += x;
        }
    }
    sort(pre.begin(), pre.end(), cmp);
    sort(post.begin(), post.end(), cmp);

    auto cal = [&](vector<Q> &que) {
        int pow = 0;
        unordered_map<int, int> vis;
        BIT bit(2 * n);
        for (auto &i: que) {
            for (int j = pow; j <= i.r; j++) {
                if (vis.count(a[j])) {
                    bit.add(vis[a[j]], -1);
                }
                bit.add(j, 1);
                vis[a[j]] = j;
            }
            pow = i.r + 1;
            ans[i.i] = bit.query(i.l, i.r);
        }
    };
    cal(pre);
    reverse(a.begin(), a.end());
    cal(post);
    for (int i = 0; i < q; i++) {
        cout << ans[i] << endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值