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

来源:互联网 发布:ubuntu中文输入法 编辑:程序博客网 时间:2024/05/16 16:11

题意:
要你维护一个带时间戳的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]);}
0 0