[POI2011]MET-Meteors

( ext{Problem})

[POI2011]MET-Meteors

( ext{Analysis})

为方便操作,我们把长度为 (m) 的环倍长,把修改 (l < r)(r) 改为 (r+m)
而后就可以整体二分了
二分答案,把需要的修改放到树状数组,检查询问时一个一个枚举其所在位置,相应划分询问,继续二分

( ext{Code})

#include<cstdio>
#define LL long long
using namespace std;

const int N = 3e5 + 5;
int n, m, cnt, p[N], h[N], ans[N];

struct node{
	int ty, l, r, a, id;
}q[N * 2], q1[N * 2], q2[N * 2];

struct edge{
	int to, nxt;
}e[N];

inline void read(int &x)
{
	x = 0; char ch = getchar();
	while (ch < '0' || ch > '9') ch = getchar();
	while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
}

inline void link(int x, int y)
{
	static int tot = 0;
	e[++tot] = edge{y, h[x]}, h[x] = tot;
}

LL c[N * 2];
inline int lowbit(int x){return  x & (-x);}
inline void add(int x, int v){for(; x <= 2 * m; x += lowbit(x)) c[x] += v;}
inline LL query(int x)
{
	LL ret = 0;
	for(; x; x -= lowbit(x)) ret += c[x];
	return ret;
}

void solve(int l, int r, int ql, int qr)
{
	if (ql > qr) return;
	if (l == r)
	{
		for(int i = ql; i <= qr; i++)
		if (!q[i].ty) ans[q[i].l] = l;
		return;
	}
	int mid = (l + r) >> 1, cnt1 = 0, cnt2 = 0;
	for(int i = ql; i <= qr; i++)
	{
		if (q[i].ty == 1)
		{
			if (q[i].id <= mid) add(q[i].l, q[i].a), add(q[i].r + 1, -q[i].a), q1[++cnt1] = q[i];
			else q2[++cnt2] = q[i];
		}
		else{
			LL sum = 0;
			for(int j = h[q[i].l]; j; j = e[j].nxt)
			{
				sum += query(e[j].to) + query(e[j].to + m);
				if (sum >= q[i].r)
				{
					q1[++cnt1] = q[i];
					break;
				}
			}
			if (sum < q[i].r) q[i].r -= sum, q2[++cnt2] = q[i];
		}
	}
	for(int i = 1; i <= cnt1; i++)
	if (q1[i].ty == 1) add(q1[i].l, -q1[i].a), add(q1[i].r + 1, q1[i].a);
	for(int i = 1; i <= cnt1; i++) q[ql + i - 1] = q1[i];
	for(int i = 1; i <= cnt2; i++) q[ql + cnt1 + i - 1] = q2[i];
	solve(l, mid, ql, ql + cnt1 - 1), solve(mid + 1, r, ql + cnt1, qr);
}

int main()
{
	read(n), read(m);
	for(int i = 1, x; i <= m; i++) read(x), link(x, i);
	for(int i = 1; i <= n; i++) read(p[i]);
	int k; read(k);
	for(int i = 1, l, r, a; i <= k; i++) 
	{
		read(l), read(r), read(a);
		if (l > r) r += m;
		q[++cnt] = node{1, l, r, a, i};
	}
	for(int i = 1; i <= n; i++) q[++cnt] = node{0, i, p[i]};
	solve(1, k + 1, 1, cnt);
	for(int i = 1; i <= n; i++)
	{
		if (ans[i] != k + 1) printf("%d
", ans[i]);
		else printf("NIE
");
	}
}
原文地址:https://www.cnblogs.com/leiyuanze/p/14970685.html