【笔记】整体二分/并行二分
口胡一下理解
例题 [POI2011]MET-Meteors
对于 m 种颜色,每个颜色的答案就是一个属于 1~Q 的数字
我们想象对于 1~Q 开一棵线段树一样的东西,最开始所有颜色都在根节点,表示这些颜色的答案所在区间一开始是 1~Q
每次模拟一遍 1~Q 所有操作,顺便将所有颜色分类到下一层;也就是在遇到某个节点的mid时判断一下这个节点内的颜色的去向
总的复杂度是nlogn*logn
#include
#include
#include
#include
#include
using namespace std;
const int MAXN = 300005;
const long long inf = 10000000000ll;
typedef long long ll;
int N, M, K, col[MAXN], des[MAXN];
struct operate {
int l, r, a;
} Q[MAXN];
struct segmentTree {
#define lson (x<<1)
#define rson (x<<1|1)
ll sum[MAXN<<2];
void clear() { memset(sum, 0, sizeof(sum)); }
void update(int x, int l, int r, int _l, int _r, int k) {
if (l>=_l && r<=_r) sum[x] += k, sum[x] = sum[x]> inf ? inf : sum[x];
else {
int mid = (l + r) >> 1;
if (mid>=_l) update(lson, l, mid, _l, _r, k);
if (mid< _r) update(rson, mid+1, r, _l, _r, k);
}
}
ll query(int x, int l, int r, int p) {
if (l==r) return sum[x];
else {
int mid = (l + r) >> 1;
if (mid>=p) return sum[x] + query(lson, l, mid, p);
else return sum[x] + query(rson, mid+1, r, p);
}
}
void print(int x, int l, int r) {
printf("[%d], [%d, %d], sum = %lld\n", x, l, r, sum[x]);
if (l< r) {
int mid = (l + r) >> 1;
print(lson, l, mid), print(rson, mid+1, r);
}
}
} ST;
struct node {
node(int _id, int _l=0, int _r=0) {
id = _id, l = _l, r = _r, m = (l + r) >> 1;
}
int id, l, r, m;
};
vector spa[MAXN];
vector vec[MAXN<<2];
queue que[2];
int ansn[MAXN];
void cal(int x, int l, int r)
{
if (l==r) {
for (auto c:vec[x]) ansn[c] = l;
} else {
int mid = (l + r) >> 1;
cal(x<<1, l, mid), cal(x<<1|1, mid+1, r);
}
}
int main()
{
scanf("%d%d", &N, &M);
for (int i=1; i<=M; i++) scanf("%d", &col[i]), spa[col[i]].push_back(i);
for (int i=1; i<=N; i++) scanf("%d", &des[i]);
scanf("%d", &K);
for (int i=1; i<=K; i++) scanf("%d%d%d", &Q[i].l, &Q[i].r, &Q[i].a);
for (int i=1; i<=N; i++) vec[1].push_back(i);
que[0].push(node(1, 1, K));
int cur = 0;
for (;; cur^=1) {
//printf("cur = %d\n", cur);
ST.clear();
for (int i=1; i<=K; i++) {
//printf(" i=%d\n", i);
if (Q[i].l<=Q[i].r) ST.update(1, 1, M, Q[i].l, Q[i].r, Q[i].a);
else ST.update(1, 1, M, 1, Q[i].r, Q[i].a), ST.update(1, 1, M, Q[i].l, M, Q[i].a);
//ST.print(1, 1, M);
//for (int o=1; o<=M; o++) printf("%lld ", ST.query(1, 1, M, o)); printf("\n");
if (!que[cur].empty() && i==que[cur].front().m) {
int x = que[cur].front().id;
int l = que[cur].front().l, r = que[cur].front().r, m = que[cur].front().m;
//printf(" [%d, %d]\n", l, r);
que[cur].pop();
for (auto c:vec[x]) {
//printf(" col = %d, ", c);
ll s = 0;
for (auto p:spa[c]) s += ST.query(1, 1, M, p);
//printf(" sum = %lld, ", s);
if (s>=des[c]) vec[x<<1].push_back(c);//, printf(" -> lson\n");
else vec[x<<1|1].push_back(c);//, printf(" -> rson\n");
}
if (l< m) que[cur^1].push(node(x<<1, l, m));
if (m+1< r) que[cur^1].push(node(x<<1|1, m+1, r));
}
}
if (que[cur^1].empty()) break;
}
cal(1, 1, K);
for (int i=1; i<=N; i++) {
ll s = 0;
for (auto p:spa[i]) s += ST.query(1, 1, M, p);
if (s< des[i]) ansn[i] = 0;
}
for (int i=1; i<=N; i++) if (ansn[i]) printf("%d\n", ansn[i]); else puts("NIE");
}