[Nowcoder 2018ACM多校第六场I] Team Rocket

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013578420/article/details/81415626

题目大意:
有n段区间, 依次使用m个点, 对于第i个点, 它删除所有与他相交的区间, 求每次删掉的区间数量, 以及每个区间是第几次被删除的。 强制在线。 ( n , m 2 10 5 , T 5 )

题目思路:
即求所有左端点<=x的区间中右端点>=x的个数。
考虑使用线段树, 每个节点维护的是左端点在区间内, 右端点递减的放在一个vector内。 建树的时候按右端点从大往小插入, 每次询问[1,x]内右端点大于等于x的区间标号, 在对应节点的vector内从头指针依次比较即可。 由于递增的性质, 每次删除的点是vector的一个前缀, 头指针依次一直往后移。 取出来后判断一下是不是第一次被删除即可。 O(nlogn)

Code:

#include <map>
#include <set>
#include <map>
#include <bitset>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

#define ll long long
#define db double
#define fi first
#define se second
#define mp(x, y) make_pair(x, y)
#define ls (x << 1)
#define rs ((x << 1) | 1)
#define mid ((l + r) >> 1)

using namespace std;

const int N = (int)2e5 + 10;
const int M = (int)2e5 + 10;
const int mo = 998244353;

int n, m, l[N], rr[N], x[N], id[N];
int die[N], ans[N];
int tot, c[M];

vector<int> vec[4 * M]; int st[4 * M];

inline int gi(){
    int ret = 0, mi = 1; char c = getchar();
    while (c < '0' || c > '9'){
        if (c == '-') mi = -1;
        c = getchar();
    }

    while (c >= '0' && c <= '9'){
        ret = ret * 10 + c - '0';
        c = getchar();
    }

    return ret * mi;
}

bool cmp(int i, int j){return rr[i] > rr[j];}

void build(int x, int l, int r){
    vec[x].clear(); st[x] = 0;

    if (l == r) return;
    build(ls, l, mid);
    build(rs, mid + 1, r);
}

void modf(int x, int l, int r, int pos, int v){
    vec[x].push_back(v);
    if (l == r) return;
    if (pos <= mid) modf(ls, l, mid, pos, v);
    else modf(rs, mid + 1, r, pos, v);
}

vector <int > ret;
void query(int x, int l, int r, int pos, int v){
    if (pos >= r){
        while (st[x] < vec[x].size() && rr[vec[x][st[x]]] >= v){
            ret.push_back(vec[x][st[x]]); st[x] ++;
        }
        return;
    }

    if (pos <= mid) query(ls, l, mid, pos, v);
    else{
        query(ls, l, mid, pos, v);
        query(rs, mid + 1, r, pos, v);
    }
}

int main(){

    int t;
    scanf("%d", &t);
    for (int cas = 1; cas <= t; cas ++){
        printf("Case #%d:\n", cas);

        scanf("%d %d", &n, &m);
        for (int i = 1; i <= n; i ++){
            l[i] = gi(), rr[i] = gi();
            c[++ tot] = l[i];
        }

        sort(c + 1, c + tot + 1);
        tot = unique(c + 1, c + tot + 1) - c - 1;

        build(1, 1, tot);
        for (int i = 1; i <= n; i ++) id[i] = i;
        sort(id + 1, id + n + 1, cmp);

        for (int i = 1; i <= n; i ++)
            modf(1, 1, tot, lower_bound(c + 1, c + tot + 1, l[id[i]]) - c, id[i]);

        int res = 0;
        for (int i = 1, x; i <= m; i ++){
            x = gi(); x ^= res;

            if (x >= c[1])
                query(1, 1, tot, upper_bound(c + 1, c + tot + 1, x) - c - 1, x);

            ans[i] = 0;
            res = 0;

            for (int j = 0; j < ret.size(); j ++)
                if (!die[ret[j]]){
                    ans[i] ++;
                    die[ret[j]] = i;
                    if (!res) res = ret[j];
                    else res = 1ll * res * ret[j] % mo;
                }

            ret.clear();

            printf("%d\n", ans[i]);
            //pi(ans[i]); puts("");
        }

        for (int i = 1; i <= n; i ++){
            //pi(die[i]);
            //putchar(' ');
            printf("%d ", die[i]);
        }

        puts("");

        for (int i = 1; i <= n; i ++) die[i] = 0;
        tot = 0;
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/u013578420/article/details/81415626