Codeforces Round #791 (Div. 2)

Codeforces Round #791 (Div. 2)

Problem A

一共有n个轮子,轮子要两两一对,如果有奇数个轮子,就肯定组装不了车。

车子要么是4轮车要么是6轮车,如果不够4个轮子,也肯定组装不了。

首先先将n个轮子两两一组,这样子讨论则变成要2组车轮或3组车轮才能变成一辆车。

如果要考虑组装的车子最多,那么就考虑全部组装4轮车。如果还有一组车轮匹配不了,那我们就去掉一台4轮车,把它变成6轮车。

如果要考虑组装的车子最少,则尽可能组装6轮车。如果有一组车轮剩余,那么去掉一台6轮车,然后加上这一组就能改造成2台4轮车。如果两组车剩余,则组一台4轮车。

考虑好这些情况即可。

// Good Good Study, Day Day AC.
#include <iostream>
#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <cstring>
#include <math.h>
#include <cmath>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <map>
#include <algorithm> 
#include <unordered_map>
#include <unordered_set>
#define ffor(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define rrep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define IOS ios::sync_with_stdio(false),cin.tie(0)
#define ll long long
#define INF 0x7f7f7f7f7f7f7f7f
#define inf 0x7f7f7f7f
#define PII pair<int,int>
#define int long long

using namespace std;



int n, T = 1;

void ready()
{
	cin >> n;
	if (n & 1 || n < 2) {
		cout << "-1\n";
		return;
	}
	n /= 2;
	if (n < 2) {
		cout << "-1\n";
		return;
	}
	int maxn = 0;
	if (n % 2 == 0) maxn = n / 2;
	else {
		if(n>2)
		  maxn = ((n - 3) / 2) + 1;
	}
	int minn = 0;
	if (n % 3 == 0) {
		minn = n / 3;
	}
	else {
		if (n % 3 == 2) {
			minn = (n - 2) / 3 + 1;
		}
		else {
			minn = (n - 4) / 3 + 2;
		}
	}
	cout << minn << ' ' << maxn << '\n';
}


void work()
{

}

signed main()
{
	IOS;
		cin>>T;
	while (T--) {
		ready();
		work();
	}
	return 0;
}



 

Problem B

用一个map来储存每个下标的值。首先输入先储存a数组的值,每次进行1操作更改数值直接更改。如果遇到操作2,则将map清空,并将答案更新为n*x。

// Good Good Study, Day Day AC.
#include <iostream>
#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <cstring>
#include <math.h>
#include <cmath>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <map>
#include <algorithm> 
#include <unordered_map>
#include <unordered_set>
#define ffor(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define rrep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define IOS ios::sync_with_stdio(false),cin.tie(0)
#define ll long long
#define INF 0x7f7f7f7f7f7f7f7f
#define inf 0x7f7f7f7f
#define PII pair<int,int>
#define int long long

using namespace std;



int n, T = 1, q, sum;
map<int, int> mp;


void ready()
{
	cin >> n >> q;
	ffor(i, 1, n) {
		int a;
		cin >> a;
		mp[i] = a;
		sum += a;
	}
}


void work()
{
	int las = 0;
	while (q--) {
		int t, i, x;
		cin >> t ;
		if (t == 1) {
			cin >> i >> x;
			if (mp[i]) sum -= mp[i];
			else  sum -= las;
			mp[i] = x;
			sum += x;
		}
		else {
			cin >> las;
			mp.clear();
			sum = n * las;
		}
		cout << sum << '\n';
	}
}

signed main()
{
	IOS;
	//	cin>>T;
	while (T--) {
		ready();
		work();
	}
	return 0;
}



 

Problem C

利用两个树状数组,一个代表行,一个代表列,每加入一个值的时候相当于单点修改,查询的时候区间查询,查询和是否等于查询长度即可。查询区间的行或列有一个方向满足即可。

// Good Good Study, Day Day AC.
#include <iostream>
#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <cstring>
#include <math.h>
#include <cmath>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <map>
#include <algorithm> 
#include <unordered_map>
#include <unordered_set>
#define ffor(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define rrep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define IOS ios::sync_with_stdio(false),cin.tie(0)
#define ll long long
#define INF 0x7f7f7f7f7f7f7f7f
#define inf 0x7f7f7f7f
#define PII pair<int,int>
#define int long long

using namespace std;


const int N = 1e5 + 5;
int n, T = 1, q;
int c[N];
int w[N];
int cntc[N], cntw[N];

int lowbite(int x) {
	return x & (-x);
}

void add_in(int temp[], int i, int add) {
	while (i <= n) {
		temp[i] += add;
		i += lowbite(i);
	}
	return;
}

int get_sum(int temp[], int x) {
	int res = 0;
	while (x) {
		res += temp[x];
		x -= lowbite(x);
	}
	return res;
}

void ready()
{
	cin >> n >> q;
	while (q--) {
		int t, x, y, xi, yi;
		cin >> t;
		if (t == 1) {
			cin >> x >> y;
			if(cntc[x]==0)
			  add_in(c, x, 1);
			if(cntw[y]==0)
			  add_in(w, y, 1);
			cntc[x]++; cntw[y]++;
		}
		if (t == 2) {
			cin >> x >> y;
			if(cntc[x]==1)
			  add_in(c, x, -1);
			if(cntw[y]==1)
			  add_in(w, y, -1);
			cntc[x]--; cntw[y]--;
		}
		if (t == 3) {
			cin >> x >> y >> xi >> yi;
			int flagx = get_sum(c, xi) - get_sum(c, x - 1);
			int flagy = get_sum(w, yi) - get_sum(w, y - 1);
			if (flagx == (xi - x + 1) || flagy == (yi - y + 1) )  {
				cout << "Yes\n";
			}
			else {
				cout << "No\n";
			}
		}
	}
}


void work()
{

}

signed main()
{
	IOS;
	//	cin>>T;
	while (T--) {
		ready();
		work();
	}
	return 0;
}



 

Problem D

最大值中的最小,首先想到的是二分,随后就是想如何check

check的时候,每次只走小于mid的点,如果能够走到一个环,那铁定是true。每个能走的点都开始走一遍,如果有一条路走的最长路径是比k还大,那么也是true,因为一定有走k步的方案满足条件。

// Good Good Study, Day Day AC.
#include <iostream>
#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <cstring>
#include <math.h>
#include <cmath>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <map>
#include <algorithm> 
#include <unordered_map>
#include <unordered_set>
#define ffor(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define rrep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define IOS ios::sync_with_stdio(false),cin.tie(0)
#define ll long long
#define INF 0x7f7f7f7f7f7f7f7f
#define inf 0x7f7f7f7f
#define PII pair<int,int>
#define int long long

using namespace std;


const int N = 2e5 + 5;
int n, T = 1, m, k;
int a[N],f[N],vis[N];
int p[N], pi, nxt[N], to[N];
bool win = false;
int maxn;
void add_in(int u, int v) {
	pi++; nxt[pi] = p[u]; p[u] = pi; to[pi] = v;
}


void ready()
{
	cin >> n >> m >> k;
	ffor(i, 1, n) cin >> a[i];
	ffor(i, 1, m) {
		int u, v;
		cin >> u >> v;
		add_in(u, v);
	}
}

void dfs(int u, int mid) {
	vis[u] = true;
	f[u] = 1;
	for (int k = p[u]; k; k = nxt[k]) {
		int v = to[k];
		if (a[v] > mid) continue;
		if (vis[v] == 1) {
			win = true;
			return;
		}
		if (!vis[v]) dfs(v, mid);
		f[u] = max(f[v] + 1, f[u]);
	}
	vis[u] = 2;
	maxn = max(maxn, f[u]);
}

bool check_(int mid) {
	maxn = win = 0;
	ffor(i, 1, n) {
		vis[i] = false;
		f[i] = 0;
	}
	ffor(i, 1, n) {
		if (!vis[i] && a[i] <= mid) {
			dfs(i, mid);
		}
	}
	if (win || k <= maxn) {
		return true;
	}
	else {
		return false;
	}
}

void work()
{
	int l = 1, r = 1e9, mid;
	while (l < r) {
		mid = (l + r) >> 1;
		//cout << l << ' ' << r << "\n";
		if (check_(mid)) {
			r = mid;
		}
		else {
			l = mid + 1;
		}
	}
	if (!check_(l)) l = -1;
	cout << l;
}

signed main()
{
	IOS;
	//	cin>>T;
	while (T--) {
		ready();
		work();
	}
	return 0;
}



 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值