版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013578420/article/details/81415626
题目大意:
有n段区间, 依次使用m个点, 对于第i个点, 它删除所有与他相交的区间, 求每次删掉的区间数量, 以及每个区间是第几次被删除的。 强制在线。
题目思路:
即求所有左端点<=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;
}