ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[POI2011]MET-Meteors

2021-07-05 08:35:16  阅读:214  来源: 互联网

标签:二分 ch Meteors int text POI2011 ++ MET cnt1


\(\text{Problem}\)

[POI2011]MET-Meteors

\(\text{Analysis}\)

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

\(\text{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\n", ans[i]);
		else printf("NIE\n");
	}
}

标签:二分,ch,Meteors,int,text,POI2011,++,MET,cnt1
来源: https://www.cnblogs.com/leiyuanze/p/14970685.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有