UVA12003 Array Transformer

题意

给定一个序列 aa,支持两种操作:

  1. 求区间 al,al+1,,ara_l, a_{l+1}, \cdots, a_r 中严格小于 vv 的数的个数。

  2. 单点修改。

解法

块内二分模板题。

考虑每一个块维护一个有序的 vector 或者其他容器,块内查询用 lower_bound,块外暴力。单点修改时修改数组的值并且用 O(nlogn)O(\sqrt{n} \log{\sqrt{n}}) 重新排序该块。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;

#define int long long

constexpr int N(3e5 + 5), M(585);

int n, m, u, len, a[N];
vector<int> p[M];

inline int get(int x)
{
	if (x == 0) return 0;
	return (x - 1) / len + 1;
}

inline int lplace(int x)
{
	return (x - 1) * len + 1;
}

inline int rplace(int x)
{
	return x * len;
}

signed main()
{
	scanf("%lld%lld%lld", &n, &m, &u);
	len = sqrt(n);
	for (register int i(1); i <= n; ++i)
	{
		scanf("%lld", &a[i]);
		p[get(i)].push_back(a[i]);
	}
	for (register int i(1); i <= len + 1; i++)
	{
		sort(p[i].begin(), p[i].end());
	}
	while (m--)
	{
		int l, r, v, pg, ans(0);
		scanf("%lld%lld%lld%lld", &l, &r, &v, &pg);
		if (get(l) == get(r))
		{
			for (int i(l); i <= r; i++) ans += a[i] < v;
		}
		else
		{
			int lp(get(l) + 1), rp(get(r) - 1);
			for (int i(lp); i <= rp; i++)
			{
				vector<int>::iterator it = lower_bound(p[i].begin(), p[i].end(), v);
				ans += (it - p[i].begin());
			}
			int lk(lplace(lp)), rk(rplace(rp));
			for (int i(l); i < lk; i++) ans += a[i] < v;
			for (int i(rk + 1); i <= r; i++) ans += a[i] < v;
		}
		int k(a[pg]);
		a[pg] = u * ans / (r - l + 1);
		*lower_bound(p[get(pg)].begin(), p[get(pg)].end(), k) = a[pg];
		//cout << ans << endl;
		sort(p[get(pg)].begin(), p[get(pg)].end());
	}
	for (int i(1); i <= n; i++) printf("%lld\n", a[i]);
	return 0;
}
posted @   HappyBobb  阅读(7)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示