首页 > 其他分享 >Best Solution Unknown

Best Solution Unknown

时间:2022-10-03 01:55:09浏览次数:74  
标签:int Unknown 最大值 Solution mid cc 下限 区间 Best

传送门

题意:
现在有n个数,每一轮可以进行的操作:取相邻的两个数进行比较,较大的获胜(若两数相同,双方都可能获胜),将较小的去除,并且较大的那个数 + 1, 两侧的数字向他靠齐。 问 n − 1 次操作后,哪些位置上的数留到了最后

思路:
对于一段区间,区间的最大值肯定能吃掉其他所有的数,因此,该最大值只要满足该区间的下限就能符合题目要求。然后分为两个两个区间递归下去。最大值的序号用线段树求一下就行。
接下来来讲下限的设置:初始情况 \([ 1 , n ]\)下限是 0。然后找到该区间的最大值的位置 m,分为 \([ 1 , m − 1 ]\)和 \([ m + 1 , r ]\)两个区间,这两个区间的下限都是 \(a [ m ]\),因为,左边的半个区间的经过若干步骤得到的一个数如果大于等于 \(a [ m ]\),那么就能继续吃掉 \(a [ m ]\) ,进而吃掉右半部分区间,反过来同理。
那么现在对于下限为 c 区间 \([ L , R ]\) ,找到最大值的位置 \(M\),此时若 \(a [ M ] + R − L\)(即最大值的位置吸收掉该区间所有数) 大于等于下限 \(C\),那么这个位置就是可以的
求这个\(c\), 首先利用上一个满足条件的式子,对于上一个满足条件的式子,分成\([L, M - 1], [M + 1, R]\)来求,对于左边,实现\(c >= a[M]\), 但是还要满足上一个的下限才可以,\(c + R - L + 1 >= c'\), 满足这两个条件,c的下限才是完备的,反之同理

总结:
擅于观察,线段树求最大值下标,递归的写法,返回什么,过程,结束条件,开始条件

点击查看代码
#include <bits/stdc++.h>
#define endl '\n'
#define IOS ios::sync_with_stdio(false);
using namespace std;

typedef long long ll;
const int MAXN = 1e6 + 10;
int n;
int a[MAXN];
bool vis[MAXN];
struct Node
{
	int l, r, pos;	//最大值的位置
} tree[MAXN << 2];

void build(int p, int l, int r)
{
	tree[p].l = l, tree[p].r = r;
	if (l == r)
	{
		tree[p].pos = l;
		return;
	}
	int mid = l + r >> 1;
	build(p << 1, l, mid);
	build(p << 1 | 1, mid + 1, r);
	tree[p].pos = a[tree[p << 1].pos] > a[tree[p << 1 | 1].pos] ? tree[p << 1].pos : tree[p << 1 | 1].pos;
}

int query(int p, int l, int r, int x, int y)
{
	if (x <= l && r <= y)
		return tree[p].pos;
	int mid = l + r >> 1;
	int index1 = 0, index2 = 0;
	if (x <= mid)
		index1 = query(p << 1, l, mid, x, y);
	if (y > mid)
		index2 = query(p << 1 | 1, mid + 1, r, x, y);
	if (index1 == 0)
		return index2;
	if (index2 == 0)
		return index1;
	return a[index1] > a[index2] ? index1 : index2;
}

void dfs(int l, int r, int c)
{
	if (l > r)
		return;
	if (l == r)
		if (a[l] >= c)
			vis[l] = 1;
	int mid = query(1, 1, n, l, r);
	if (a[mid] + r - l >= c)
	{
		vis[mid] = 1;
		int cc = max(a[mid], c + mid - r - 1);
		dfs(l, mid - 1, cc);
		cc = max(a[mid], c - mid + l - 1);
		dfs(mid + 1, r, cc);
	}
}

int main()
{
	IOS; cin.tie(0), cout.tie(0);
	cin >> n;
	for (int i = 1; i <= n; ++i)
		cin >> a[i];
	build(1, 1, n);
	dfs(1, n, 0);
	int ans = 0;
	for (int i = 1; i <= n; ++i)
		if (vis[i])
			++ans;
	cout << ans << endl;
	for (int i = 1; i <= n; ++i)
		if (vis[i])
			cout << i << " ";
	return 0;
}

标签:int,Unknown,最大值,Solution,mid,cc,下限,区间,Best
From: https://www.cnblogs.com/jumo-xiao/p/16749884.html

相关文章