CF1080F Katya and Segments Sets

时间:2023-03-09 19:28:55
CF1080F Katya and Segments Sets

题意:给定n个区间,每个区间有颜色。m次询问,每次询问:这n个区间中所有被包含在[x, y]这一区间中的区间,它们的颜色是否取遍了[l, r]中的所有颜色。

强制在线。

解:第一步是大家都熟悉的套路⑧,把这些区间按照左端点排序。

然后从右往左加区间,用一个可持久化数据结构维护答案。

然后我在这里就被套路住了......一般来说是线段树上x维护右端点为x的答案。但是本题要把第二维换一下。

主席树的版本仍旧是左端点。但是线段树上每个位置维护的是该颜色的区间,结尾的最小值。

然后查询,我们就查对应版本对应颜色区间的全体最大值是否大于y。大于y表示那个颜色无解。输出no。否则输出yes。

 #include <bits/stdc++.h>

 const int N = , M = , INF = 0x7f7f7f7f;

 struct Node {
int l, r, c;
inline bool operator <(const Node &w) const {
return l < w.l;
}
}node[N]; int ls[M], rs[M], large[M], tot;
int xx, q, n, lm, X[N], rt[N]; void insert(int &x, int y, int p, int v, int l, int r) {
if(!x || x == y) {
x = ++tot;
ls[x] = ls[y];
rs[x] = rs[y];
large[x] = large[y];
}
if(l == r) {
large[x] = std::min(large[x], v);
return;
}
int mid = (l + r) >> ;
if(p <= mid) insert(ls[x], ls[y], p, v, l, mid);
else insert(rs[x], rs[y], p, v, mid + , r);
large[x] = std::max(large[ls[x]], large[rs[x]]);
//printf("[%d %d] large = %d \n", l, r, large[x]);
return;
} int ask(int L, int R, int l, int r, int o) {
if(!o) return INF;
if(L <= l && r <= R) return large[o];
int mid = (l + r) >> , ans = -INF;
if(L <= mid) ans = std::max(ans, ask(L, R, l, mid, ls[o]));
if(mid < R) ans = std::max(ans, ask(L, R, mid + , r, rs[o]));
return ans;
} int main() {
memset(large, 0x7f, sizeof(large));
scanf("%d%d%d", &lm, &q, &n);
for(int i = ; i <= n; i++) {
scanf("%d%d%d", &node[i].l, &node[i].r, &node[i].c);
X[i] = node[i].l;
}
std::sort(node + , node + n + );
std::sort(X + , X + n + );
xx = std::unique(X + , X + n + ) - X - ;
for(int i = n; i >= ; i--) {
node[i].l = std::lower_bound(X + , X + xx + , node[i].l) - X;
/// build
insert(rt[node[i].l], rt[node[i].l + ], node[i].c, node[i].r, , lm);
//printf("insert %d %d rt[%d] \n", node[i].c, node[i].r, node[i].l);
} /*printf("X : ");
for(int i = 1; i <= xx; i++) {
printf("%d ", X[i]);
}
puts("");*/ for(int i = , x, y, l, r; i <= q; i++) {
scanf("%d%d%d%d", &l, &r, &x, &y);
int t = std::lower_bound(X + , X + xx + , x) - X; //printf("i = %d t = %d \n", i, t); if(t > xx) {
printf("no\n");
//printf("ERROR 1 \n");
}
else {
t = ask(l, r, , lm, rt[t]);
if(t > y) printf("no\n");
else printf("yes\n");
//printf("t = %d \n", t);
}
fflush(stdout);
} return ;
}

AC代码