MX 炼石计划 NOIP 模拟赛20(我真做过1~19吗?)

MX 炼石计划 NOIP 模拟赛 #20

T1 邻间的骰子之舞

二分答案,发现性质,签到,过。

记得开 __int128

没开,挂 30.

码:

CODE
#include <bits/stdc++.h>
typedef long long ll; 
using namespace std; 
const int N = 2e5 + 100; 

#ifdef linux
#define getchar getchar_unlocked
#define putchar putchar_unlocked
#endif
inline int read() {
	int x = 0; char c = getchar(); 
	while (c < '0' || c > '9') c = getchar(); 
	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); 
	return x; 
}
template <typename T> void write(T x) {
	if (x / 10) write(x / 10); 
	putchar(x % 10 + '0'); 
}

ll n, x, y; 
ll maxer; 

inline bool check(__int128 mid) {
	for (__int128 i = 0; i <= maxer; ++ i) {
		if (i * x >= mid) break; 
		if (i == 0) {
			if ((mid - i * x) / y + 1 > n) return true; 
			continue; 
		}

		__int128 j = (mid - i * x) / y, val = 1, aver = j / (i + 1), last = j - aver * (i + 1); 
		for (ll k = 0; k <= i; ++ k) {
			if (last > 0) {
				val += (aver + 1) * val, last --; 
			} else val += aver * val; 
			if (val > n) return true; 
		}
	}

	return false; 
}

signed main() {
	freopen("dice.in", "r", stdin); 
	freopen("dice.out", "w", stdout); 
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); 
	cin >> n >> x >> y; 

	__int128 l = 1, r = 1e19, ans = 0; maxer = log2(n); 

	while (l <= r) {
		__int128 mid = ((__int128)(l + r) >> 1ll); 

		if (check(mid)) {
			ans = mid, r = mid - 1; 
		} else l = mid + 1; 
	}

	write(ans + x); 
}

T2 星海浮沉录

签到2,拿 \(set\) 维护一下每种数位置以及两者之间距离,然后线段树上二分。

码:

CODE
#include <bits/stdc++.h>
typedef long long ll; 
using namespace std; 
const int N = 5e5 + 100; 

#ifdef linux
#define getchar getchar_unlocked
#define putchar putchar_unlocked
#endif
inline int read() {
	int x = 0; char c = getchar(); 
	while (c < '0' || c > '9') c = getchar(); 
	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); 
	return x; 
}
template <typename T> void write(T x) {
	if (x / 10) write(x / 10); 
	putchar(x % 10 + '0'); 
}

int n, q; int a[N]; 
int last[N]; 
multiset <int> num[N], dis[N]; 

#define lson (id << 1)
#define rson (id << 1 | 1)
#define mid ((l + r) >> 1)

int t[N << 2]; 
void updata(int id, int l, int r, int x, int c) {
	if (l == r) return t[id] = c, void(); 
	return ((x <= mid) ? updata(lson, l, mid, x, c) : updata(rson, mid + 1, r, x, c)), t[id] = max(t[lson], t[rson]), void(); 
}
int Query(int id, int l, int r, int k) {
	if (l == r) return l; 
	if (t[lson] >= k) return Query(lson, l, mid, k); 
	else return Query(rson, mid + 1, r, k); 
}

#undef mid

#define iter set <int>::iterator

inline void change(int x, int i, int j) {
	iter it = num[x].lower_bound(i), it2 = ++ it; -- it; 

	if (it != num[x].begin()) {
		int fir = *(-- it); ++ it; 
		dis[x].erase(dis[x].lower_bound(i - fir - 1)), dis[x].insert(j - fir - 1); 
	}
	if (it2 != num[x].end()) {
		int sec = *it2; 
		dis[x].erase(dis[x].lower_bound(sec - i - 1)), dis[x].insert(sec - j - 1); 
	}

	num[x].erase(i), num[x].insert(j); 
	updata(1, 0, n + 1, x, *dis[x].rbegin()); 
}

signed main() {
	freopen("star.in", "r", stdin); 
	freopen("star.out", "w", stdout); 
	n = read(), q = read(); 
	for (int i = 0; i <= n; ++ i) num[i].insert(0); 
	for (int i = 1; i <= n; ++ i) {
		a[i] = read(), num[a[i]].insert(i); 
		dis[a[i]].insert(i - last[a[i]] - 1); 
		last[a[i]] = i; 
	}
	for (int i = 0; i <= n; ++ i) {
		dis[i].insert(n - *num[i].rbegin()); num[i].insert(n + 1); 
		updata(1, 0, n + 1, i, *dis[i].rbegin()); 
	}

	int opt, x, tot = 0; 
	while (q --) {
		opt = read(), x = read(); 

		if (opt == 1) {
			if (a[x] == a[x + 1]) continue; 
			change(a[x], x, x + 1); 
			change(a[x + 1], x + 1, x); 
			swap(a[x], a[x + 1]); 
		} else {
			write(Query(1, 0, n + 1, x)), puts(""); 
		}
	}
}

注:byd梦熊还有什么逆天文件问题,甚至还只有一个测试点有文件问题?唐。

T3 勾指起誓

不会,咕了。

T4 _八交响曲

赛时没想出来。

考虑两个有序数组合并,只需要将镜像位置交换之后,发现其左右儿子区间保证左大于右或右大于左这么一个情况,遍历他儿子的时候就可以按位置交换了,非常优秀。

CODE
#include <bits/stdc++.h>
typedef long long ll; 
using namespace std; 
const int N = 200; 

int n; int m; 
vector <pair <int, int> > v[N]; 
int pos[N][N], pos2[N]; 

void Solve2(int l, int r, int dep, int ac) {
	if (l == r) return; 
	if (!pos[ac][dep]) pos[ac][dep] = ++ m; 
	int mid = (l + r) >> 1; 
	for (int i = l; i <= mid; ++ i) {
		int now = mid + i - l + 1; 
		if (now <= r && now != i) v[pos[ac][dep]].push_back(make_pair(i, now)); 
	}

	Solve2(l, mid, dep + 1, ac), Solve2(mid + 1, r, dep + 1, ac); 
}

void Solve(int l, int r, int dep) {
	if (l == r) return; 
	int mid = (l + r) >> 1; 
	Solve(l, mid, dep + 1), Solve(mid + 1, r, dep + 1); 
	if (!pos2[dep]) pos2[dep] = ++ m; 
	for (int i = 1; i <= mid; ++ i) 
		if (l + i - 1 < r - i + 1)
			v[pos2[dep]].push_back(make_pair(l + i - 1, r - i + 1)); 
	Solve2(l, mid, dep + 1, dep), Solve2(mid + 1, r, dep + 1, dep); 
}

signed main() {
	freopen("symphony.in", "r", stdin); 
	freopen("symphony.out", "w", stdout); 
	cin >> n; int p = n; 
	n = pow(2, ceil(log2(n))); 
	Solve(1, n, 1); 
	cout << m << '\n'; 

	for (int i = 1; i <= m; ++ i) {
		for (auto j : v[i]) {
			if (j.first <= p && j.second <= p)
			printf("CMPSWP R%d R%d ", j.first, j.second); 
		} puts(""); 
	}
}

总结

70(-30) + 100(-0) + 12(-0) + 10(-0)

中学生誓词

泌阳的我再不看数据规模瞎几把用龙龙并认为龙龙可以拯救一切我就踏马的玩原神吃鸡屎及防盗管被合一哟纸发现再回去玩宝宝巴士和迷奥迷奥看三国志!!!

作者:hangry

出处:https://www.cnblogs.com/hangry/p/18546440

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   HANGRY_Sol&Cekas  阅读(114)  评论(19编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示
more_horiz
keyboard_arrow_up light_mode palette
选择主题