2023江西省省赛H、J题题解

原题链接

1. H题

* 题意:给你一个长度为n的排列,根据规则能否找到原排列。

* 思路:刚开始我也无头乱撞,疯狂模拟数据,就发现了每个数在遇到比自己大的数之前的所有数一定是在一堆中的。然后我就按这个性质分成多堆,又发现它们可以随机组合成新的一堆,就想到用背包写,看分成的堆能否大小为"n/2",如果有一堆大于“n/2”可以直接输出“NO”了.

刚开始就想着简单01背包加一点优化看能不能过,样例25超时了,后面没办法在想着优化就用二进制,多重背包的思想了,因为不同的物品很少,极限的种类就是 \(\sqrt{n}\) 种。

void solve()
{
	int n;
	cin >> n;
	vector<int> b;
	for (int i = 1; i <= n; i ++) cin >> a[i];
	int res = a[1], cnt = 1, ans = n / 2;
	b.push_back(0);
	for (int i = 2; i <= n; i ++)
	{
		s[i] = 0, f[i] = 0;
		res = max(a[i], res);
		if (res == a[i])
		{
			b.push_back(cnt);
			cnt = 1;
		}
		else 
		{
			cnt ++;
			if (cnt > ans) {cout << "No" << '\n';return;}
		}
	}
	b.push_back(cnt);
	// for (int i = 1; i < b.size(); i ++) cout << b[i] << " \n"[i == n];
	
	for (int i = 1; i < b.size(); i ++) 
	{
		if (s[i] >= ans) s[i] = ans;
		else s[i] = s[i - 1] + b[i];
	}
	for (int i = 0; i <= ans; i ++) f[i] = 0;
	f[0] = 1;
	
	for (int i = 1; i < b.size(); i ++)
	{
		for (int j = min(s[i], ans); j >= b[i]; j --)
		{
			f[j] += f[j - b[i]];
		}
		if (f[ans] >= 1) {cout << "Yes" << '\n';return;}
	}
	
	cout << "No" << '\n'; 
}

void solve()
{
	int n;
	cin >> n;
	map<int, int> mp;
	for (int i = 1; i <= n; i ++) cin >> a[i];
	
	int res = a[1], cnt = 1, ans = n / 2;
	
	for (int i = 2; i <= n; i ++)
	{
		res = max(a[i], res);
		if (res == a[i])
		{
			mp[cnt] ++;
			cnt = 1;
		}
		else 
		{
			cnt ++;
			if (cnt > ans) {cout << "No" << '\n';return;}
		}
	}
	mp[cnt] ++;
	
	vector<int> c;
	for (auto t : mp)
	{
		int cot = 1;
		while (t.second >= cot)
		{
			c.push_back(t.first * cot);
			t.second -= cot;
			cot *= 2;
		}
		if (t.second > 0) c.push_back(t.second * t.first);
	}
	
	for (int i = 0; i <= ans; i ++) f[i] = 0;
	f[0] = 1;
	for (int i = 0; i < c.size(); i ++)
	{
		for (int j = ans; j >= c[i]; j --)
		{
			f[j] += f[j - c[i]];
		}
		if (f[ans] >= 1) {cout << "Yes" << '\n';return;}
	}
	cout << "No" << '\n'; 
}

2.J题

题目:

英语也不好,刚开始做的时候题目都看不懂,感觉题意是难点。

题意:就是两个操作,在询问操作中当x=a时,取哪个位置是答案最小,第二个操作就是对位置a的值b[i]取个min。

思路:就是当\(n^2\) 大于两倍的1e5的时候,取最小值的时候,值b[i]的影响就约等于没有了,那在这题就可以暴力了。

void solve()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; i ++) cin >> b[i];
	
	int m;
	cin >> m;
	while (m --)
	{
		int op;
		cin >> op;
		if (op == 1)
		{
			int a, ans = 1e18;
			cin >> a;
			for (int i = max(1ll, a - 500); i <= min(n, a + 500); i ++)
			{
				int res = (a - i) * (a - i) + b[i];
				ans = min(ans, res);
			}
			cout << ans << '\n';
		}
		else 
		{
			int x, y;
			cin >> x >> y;
			b[x] = min(b[x], y);
		}
	}
}
posted @ 2023-05-23 16:53  N再再  阅读(372)  评论(0)    收藏  举报