专栏文章

黑洞 暴力二分 峰值37ms可过

个人记录参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mip6n57g
此快照首次捕获于
2025/12/03 07:01
3 个月前
此快照最后确认于
2025/12/03 07:01
3 个月前
查看原文
刚开始的思路是搓一个O(LogN+MLogN)O(LogN+M*LogN)的暴力二分
显然由于极限情况下M=1e9M=1e9,因此T,只得72pts
用vector去重后,每次跳到二分的变化界限,重复的数以乘代加
优化为O(LogN+NLogN)O(LogN+N*LogN),轻松过oj;洛谷峰值82ms
代码:
C
//纯暴力+vec优化,跑得飞快
//时间复杂度:O(N*LogN+LogN)

#include<bits/stdc++.h>
#define N 200005
#define int long long
#define inf 0x3f3f3f3f3f3f3f3f
#define mod (int)(1e9+7)
using namespace std;
class Quick_IO
{
  public:
	template<typename T>
	void read(T &r)
	{
		T x = 0, f = 1;
		char ch = getchar();
		while (ch < '0' || ch > '9')
		{
			if (ch == '-') f = -1;
			ch = getchar();
		}
		while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
		r = x * f;
	}
	template<typename T, typename... Args>
	void read(T &tmp, Args &... tmps)
	{
		read(tmp);
		read(tmps...);
	}
} io;
#define Freopen \
	freopen("hole.in", "r", stdin); \
	freopen("hole.out", "w", stdout);


int n, High = inf, ans, Last;
int Low[N], m[N];
vector<int> Low2;
#define siz2 (Low2.size())

int Pow(int a, int n, int p)   //快速幂求 a^n % p
{
	int ans = 1;
	while (n)
	{
		if (n & 1) ans = ans * a % p;
		a = a * a % p;
		n >>= 1;
	}
	return ans;
}

signed main()
{
	//Freopen;
	io.read(n);
	for (int i = 1; i <= n; i++) io.read(m[i]);
	for (int i = 1, a; i <= n; i++)
	{
		io.read(a);
		Low[i] = min(a - 1, m[i] - a);
		High = min(High, max(a - 1, m[i] - a));	//最大边界
	}

	sort(Low + 1, Low + 1 + n);		//排序
	for (int i = 1; i <= n; i++)	//去重
	{
		if (Low[i] >= High) break;	//大的不要
		if (siz2 == 0) Low2.emplace_back(Low[i]);
		else if (Low2[siz2 - 1] < Low[i]) Low2.emplace_back(Low[i]);
	}
	Low2.emplace_back(High);

	for (int i = 0, k, z, t; i < siz2; i++)
	{
		k = Low2[i], t = k - Last;	//t代表需要加几次,乘法代替以前枚k++
		z = Low + 1 + n - lower_bound(Low + 1, Low + 1 + n, k);	//获取当前大于等于k的有几个
		ans += (Pow(2, z, mod) * (t % mod)) % mod;
		ans %= mod, Last = k;
	}
	cout << (ans + 1) % mod;	//黑洞自身
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...