[CDQ分治] codeforces 669E. Little Artem and Time Machine

題意:
要你維護一個帶時間戳的multiset,有三種操作。
- 形如:1 a b ,在第a秒插入1個b。
- 形如:2 a b ,在第a秒刪除1個b。
- 形如:3 a b ,查詢當前在a秒時有多少個b。
需要注意輸入有順序,multiset自己也有時間戳。
題解:
感覺CDQ可以做,2維的,寫了一發然後AC了,第一次獨立寫CDQ。
我對CDQ理解也不深,不亂說了,直接看代碼比較簡單。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
struct op{
    int tp, sp, x, id;
    op(){}
    op(int a, int b, int c, int d) { tp = a, sp = b, x = c, id = d; }
    bool operator < (const op& a) const{ return sp < a.sp; }
}qry[N];
map<int,int>st;
int ans[N] = {0};
bool vis[N] = {0};
int acnt = 0;
inline bool cmp(const op& a, const op& b){
    return a.id < b.id;
}
void CDQ(int l, int r){
    if(l >= r) return;
    int mid = (l+r) >> 1;
    CDQ(l, mid);
    CDQ(mid+1, r);
    sort(qry+l, qry+r+1);
    for(int i = l; i <= r; ++i){
        op& x = qry[i];
        if(x.id <= mid){
            if(x.tp == 1) st[x.x] += 1;
            else if(x.tp == 2) st[x.x] -= 1;
        }
        else { if(x.tp == 3) ans[x.id] += st[x.x]; }
    }
    for(int i = l; i <= r; ++i){
        op& x = qry[i];
        if(x.id <= mid){
            if(x.tp == 1) st[x.x] -= 1;
            else if(x.tp == 2) st[x.x] += 1;
        }
    }
    sort(qry+l, qry+r+1, cmp);
}
int main(){
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i){
        scanf("%d%d%d", &qry[i].tp, &qry[i].sp, &qry[i].x);
        qry[i].id = i;
        if(qry[i].tp == 3) vis[i] = 1;
    }
    CDQ(1, n);
    for(int i = 1; i <= n; ++i) if(vis[i]) printf("%d\n", ans[i]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章