8.4 思维构造

P5019 [NOIP2018 提高组] 铺设道路 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

 例如一个序列4 3 2 1 5 4 5

由贪心可知必然是一次选择的区间越大越好,所以每次处理一个不包括0的不上升区间即可,因为对一个不上升区间来说,要使其全部为0最多需要操作max(l-r)次,因为比区间最大值小的数消去相当于是免费的。所以统计不上升区间的最大值即可。

#include<bits/stdc++.h>
using namespace std;
#define int long long 
#define rep(j,b,e) for(int j=(b);j<=(e);j++)
#define drep(j,e,b) for(int j=(e);j>=(b);j--)
const int N = 1e5 + 10;
int n, m, q, k;

signed main() {
#ifndef ONLINE_JUDGE
	//freopen("out.txt", "w", stdout);
#endif
	ios::sync_with_stdio(0); cout.tie(0);
	int n;
	cin >> n;
	vector<int>arr(N);
	int mx = INT_MIN;
	int ans = 0;
	rep(j, 1, n) {
		int t;
		cin >> arr[j];
		if (arr[j] > arr[j - 1])ans += (arr[j] - arr[j - 1]);//当后一个数严格大于前一个数说明进入下一个不上升区间
	}
	cout << ans;
	
}

 CF1711B Party - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

如果当作图论来看就是,减去给定图的一些节点使剩下的边数为偶数时最小消耗。

 如果边数本身就是偶数时,就不需要减去了,最小消耗为0.

如果边数为奇数时,就要考虑减去奇数条边,且顶点消耗最小。对这种情况由两种方案,

1.删去度为奇数的顶点,图的边自然减少奇数条

2.删去一条边,至多两个顶点,再多删去边由贪心可知必然劣于只删去一条边。

1很好理解,因为是无向图,一个度为一条边。

2比较困难,我们要删去一条边则需要保证剩下的顶点构成的边数要为偶数,那么删去这条边的两个顶点的度之和必须为偶数,因为这两个顶点有一条公共边,只有这样删去这两个顶点后总边数减少了(n+m)-1,当度之和(n+m)为偶数时,才会减少奇数条边。

#include<bits/stdc++.h>
using namespace std;
#pragma warning(disable:4996);
#define int long long 
#define rep(j,b,e) for(int j=(b);j<=(e);j++)
#define drep(j,e,b) for(int j=(e);j>=(b);j--)
const int N = 5e5 + 10;
int T = 1;
int n, m, q, k;

using edg = pair<int, int>;
edg tem[N];
vector<int>gra[N];
signed main() {
#ifndef ONLINE_JUDGE
	freopen("out.txt", "w", stdout);
#endif
	ios::sync_with_stdio(0); cout.tie(0);
	cin >> T;
	while (T--) {
		cin >> n >> k;
		vector<int>arr(1);

		rep(j, 1, n) {
			int t;
			cin >> t;
			arr.push_back(t);
			gra[j].clear();
		}
		int ans = INT_MAX;
		rep(j, 1, k) {
			int a, b;
			cin >> a >> b;
			tem[j] = { a,b };
			gra[a].push_back(b);
			gra[b].push_back(a);
		}
		rep(j, 1, n) {
			if (gra[j].size() % 2)
				ans = min(ans, arr[j]);
		}
		rep(j, 1, k) {
			auto [a, b] = tem[j];
			if ((gra[a].size() + gra[b].size()) % 2 == 0)
				ans = min(ans, arr[a] + arr[b]);
		}
		if (k % 2 == 0)
			cout << 0 << " \n";
		else
			cout << ans << endl;
	}
}

1025. 除数博弈 - 力扣(LeetCode)

 如果n为奇数,每次只能选择减去一个奇数,因为奇数的因数也为奇数,此时n变为偶数

如果n为偶数,那么可以选择减去偶数或者1.

当玩家遇到1,游戏结束,该玩家失败。

也就是说,当碰到偶数的情况,玩家可以选择让这个数变成奇数或者偶数,所以如果开局就是偶数,那么我们只需要每次将得到的数改为奇数,对方只能将这个数改为偶数,所以我们每次得到得到数都会是偶数,直到遇到2,使对方遇到1游戏胜利。所以只有开局是偶数则赢

class Solution:
    def divisorGame(self, n: int) -> bool:
        if n%2==0:
            return True
        return False

4.292. Nim 游戏 - 力扣(LeetCode)

 可知每个人最少都必须拿走1块石头,剩余石头少于等于3时胜利。所以当当前石头为4时该玩家必定失败。所以如果当对方石头数为4时才能获胜。所以必须初始石头必须不是4的倍数时才能获胜。

如果当对方石头数是4的倍数的时候,对方拿掉k个石头,我们可以拿掉4-k个石头保证剩下的石头仍然是4的倍数。同理,如果初始石头数是4的倍数,我们拿了k,对方可以拿4-k,此时我们的石头数永远是4的倍数直到4.我们必输。

所以初始石头数不是4的倍数我们才能赢

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值