Codeforces Round 946 (Div. 3)

Codeforces Round 946 (Div. 3)

A.Phone Desktop

  • 思路:先分配sreen给2x2的,再把边角料分配给1x1的,如果不够再去拿新的sreen
  • 代码:
/*
* @Author: 	Hfuubigstrength
* @email:	2854614012@qq.com
* @Date:   2024-05-20 22:44:10
*/
#include <bits/stdc++.h>
// #define int long long
#define PII pair<int,int>
#define LL long long
#define fi first
#define se second
#define debug(a) cout<<#a<<"="<<a<<endl;
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define sz(x) (int)x.size()
using namespace std;

void solve(){
	int a, b;
	cin >> a >> b;
	int cnt = b / 2 + (b % 2 != 0);
	int sheng = 15 * cnt - b * 4;
	if(sheng < a){
		cnt += (a - sheng) / 15 + ((a - sheng) % 15 != 0);
	}
	cout << cnt << endl;
}

signed main(){
	ios::sync_with_stdio(false);cin.tie(0);
	int tt = 1;
	cin >> tt;
	while(tt -- ){
		solve();
	}
	return 0;
}

B.Symmetric Encoding

  • 思路:先去重求出字符数组,对于每一个i找到对称的字符即可
  • 代码:
/*
* @Author: 	Hfuubigstrength
* @email:	2854614012@qq.com
* @Date:   2024-05-20 23:02:06
*/
#include <bits/stdc++.h>
// #define int long long
#define PII pair<int,int>
#define LL long long
#define fi first
#define se second
#define debug(a) cout<<#a<<"="<<a<<endl;
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define sz(x) (int)x.size()
using namespace std;

int n;
string s;
void solve(){
	map<char,int>mp;
	cin >> n >> s;
	vector<char>q;
	for(int i = 0; i < n; i ++ ){
		if(mp[s[i]] == 0){
			q.pb(s[i]);
			mp[s[i]] ++;
		}
	}
	sort(all(q));
	int m = q.size();
	//对称 i -> m - i - 1
	map<char,char>mp1;
	for(int i = 0; i < m; i ++ ){
		mp1[q[i]] = q[m - i - 1];
	}
	for(auto it : s){
		cout << mp1[it];
	}
	cout << endl;
}

signed main(){
	ios::sync_with_stdio(false);cin.tie(0);
	int tt = 1;
	cin >> tt;
	while(tt -- ){
		solve();
	}
	return 0;
}

C.Beautiful Triple Pairs

  • 用map存 a i , a i + 1 , a i + 2 a_i, a_{i +1}, a_{i + 2} ai,ai+1,ai+2三个有两个一样的数目num,然后对于num超过1个的任意选两个,最后减去不合法的三个都是一样的方案数
  • 代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;

map<array<int,3>,int>mp, mp1;
int a[200010];
int INF = 2e6;
int n;

void solve(){
    mp.clear();
    mp1.clear();
    cin >> n;
    for(int i = 1; i <= n; i ++ ){
        cin >> a[i];
    }
    for(int i = 1; i <= n - 2; i ++ ){
        mp[{INF, a[i + 1], a[i + 2]}] ++;
        mp[{a[i], INF, a[i + 2]}] ++;
        mp[{a[i], a[i + 1], INF}] ++;
        mp1[{a[i], a[i + 1], a[i + 2]}] ++;
    }
    int ans = 0;
    for(auto [x, y] : mp){
        ans += (y - 1) * y / 2;
    }
    for(auto [x, y] : mp1){
        ans -= 3 * (y - 1) * y / 2;
    }
    cout << ans << endl;
}

signed main(){
    int tt;
    cin >> tt;
    while(tt -- ){
        solve();
    }
}

D.Ingenuity-2

  • 思路:

    如果某个方向上比相反方向多奇数个,无法平均分配

    如果出现n = 2,且两个方向不一样的,也无法分配

    其余模拟

  • 代码:

/*
*@Author: 	Hfuubigstrength
* @email:	2854614012@qq.com
* @Date:   2024-05-20 23:56:06
*/
#include <bits/stdc++.h>
// #define int long long
#define PII pair<int,int>
#define LL long long
#define fi first
#define se second
#define debug(a) cout<<#a<<"="<<a<<endl;
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define sz(x) (int)x.size()
using namespace std;

int n;
string s;
bool st[200010];
char ans[200010];

void solve(){
	int N = 0, S = 0, W = 0, E = 0;
	cin >> n >> s;
	for(int i = 0; i < n; i ++) st[i] = 0;
	for(auto it : s){
		if(it == 'S') S ++;
		if(it == 'N') N ++;
		if(it == 'W') W ++;
		if(it == 'E') E ++;
	}
	if(abs(S - N) % 2 || abs(W - E) % 2){
		cout << "NO\n";
		return;
	}
	int cntn = 0, cnts = 0, cntw = 0, cnte = 0;
	if(S > N) cnts = abs(S - N) / 2;
	else cntn = abs(S - N) / 2;
	if(W > E) cntw = abs(W - E) / 2;
	else cnte = abs(W - E) / 2;
	for(int i = 0; i < n; i ++ ){
		if(s[i] == 'S' && cnts -- > 0) st[i] = 1;
		if(s[i] == 'W' && cntw -- > 0) st[i] = 1;
		if(s[i] == 'E' && cnte -- > 0) st[i] = 1;
		if(s[i] == 'N' && cntn -- > 0) st[i] = 1;
	}
	int sum = 0;
	for(int i = 0; i < n; i ++ ){
		sum += st[i];
	}
	for(int i = 0; i < n; i ++ ){
		if(st[i]) ans[i] = 'H';
		else ans[i] = 'R';
	}
	int a = -1, b = -1, c = -1, d = -1;
	if(sum == 0){
		if(n == 2){
			cout << "NO\n";
			return;
		}
		for(int i = 0; i < n; i ++ ){
			if(s[i] == 'S' && a < 0) a = i;
			if(s[i] == 'W' && b < 0) b = i;
			if(s[i] == 'E' && c < 0) c = i;
			if(s[i] == 'N' && d < 0) d = i;
		}
		if(a >= 0 && d >= 0){
			ans[a] = 'H';
			ans[d] = 'H';
		}else if(b >= 0 && c >= 0){
			ans[b] = 'H';
			ans[c] = 'H';
		}else{
			cout << "NO\n";
			return;
		}
	}
	if(sum == n){
		if(n == 2){
			cout << "NO\n";
			return;
		}
		for(int i = 0; i < n; i ++ ){
			if(s[i] == 'S' && a < 0) a = i;
			if(s[i] == 'W' && b < 0) b = i;
			if(s[i] == 'E' && c < 0) c = i;
			if(s[i] == 'N' && d < 0) d = i;
		}
		if(a >= 0 && d >= 0){
			ans[a] = 'R';
			ans[d] = 'R';
		}else if(b >= 0 && c >= 0){
			ans[b] = 'R';
			ans[c] = 'R';
		}else{
			cout << "NO\n";
			return;
		}		
	}
	for(int i = 0; i < n; i ++ ){
		cout << ans[i];
	}
	cout << "\n";
}

signed main(){
	ios::sync_with_stdio(false);cin.tie(0);
	int tt = 1;
	cin >> tt;
	while(tt -- ){
		solve();
	}
	return 0;
}

E.Money Buys Happiness

  • 思路:dp[i]表示,前i个月,换欢乐值为j的剩余的钱的最大值,dp一下,看最后剩余的钱是不是大于等于0即可。
    • dp初始化为负无穷大, d p [ 0 ] dp[0] dp[0]为0,
    • 转移:当当前的i比当前当前月份的欢乐值大,且这个月之前的 j − h [ i ] j-h[i] jh[i]的剩余的值是大于等于c[i]的,就可以转移过来,剩下的钱就是 d p [ j − h [ i ] ] − c [ i ] dp[j - h[i]] - c[i] dp[jh[i]]c[i],最后如果 d p [ i ] dp[i] dp[i]合法,也就是大于等于0,我们可以加上当前月份的钱。
  • 代码
#include <bits/stdc++.h>
#define debug(x) cout <<#x << " = " << x << endl;
using namespace std;

const int N = 100;
int n, x;
int c[N], h[N];
long long dp[100010];//表示快乐值能达到i的剩下的money

void solve(){
	cin >> n >> x;
	memset(dp, 0, sizeof dp);
	int sum = 0;
	for(int i = 1; i <= n; i ++ ){
		cin >> c[i] >> h[i];
		sum += h[i];
	}
	for(int i = 0; i <= sum; i ++ ) dp[i] = -9e18;
	dp[0] = 0;
	for(int i = 1; i <= n; i ++ ){
		for(int j = sum; j >= 0; j -- ){
			if(j >= h[i] && dp[j - h[i]] >= c[i]){ 
				dp[j] = max(dp[j], dp[j - h[i]] - c[i]);

			}
			dp[j] += x;
		}
	}
	int ans = 0;
	for(int i = 0; i <= sum; i ++ ){
		if(dp[i] >= 0) ans = i;
	}
	cout << ans << endl;
}

int main(){
	int tt;
	cin >> tt;
	while(tt -- ){
		solve();
	}
	return 0;
}

F.Cutting Game

  • 思路:离线处理。我们先预处理出所有操作后的矩形,然后对于每一个point二分出在哪一个操作被消除的,就给对应的人加分
  • 代码:
#include <bits/stdc++.h>
#define debug(x) cout << #x << " = " << x  << endl;
using namespace std;

int a, b, n, m;
vector<array<int,2>>point;
vector<array<int,4>>rec;
void solve(){
	rec.clear();point.clear();
	cin >> a >> b >> n >> m;
	for(int i = 1; i <= n; i ++ ){
		int x, y; cin >> x >> y;
		array<int,2>z; z[0] = x, z[1] = y;
		point.push_back(z);
	}
	int x1 = 1, x2 = a, y1 = 1, y2 = b;
	rec.push_back({x1, y1, x2, y2});
	for(int i = 1; i <= m; i ++ ){
		char c; int x;
		cin >> c >> x;
		if(c == 'U') x1 += x;
		if(c == 'D') x2 -= x;
		if(c == 'L') y1 += x;
		if(c == 'R') y2 -= x;
		rec.push_back({x1, y1, x2, y2});
	}
	int ans1 = 0, ans2 = 0;
	for(int i = 0; i < n; i ++ ){
		//二分每一个节点被删去的操作下标
		int l = 1, r = m;
		while(l < r){
			int mid = l + r >> 1;
			if(point[i][0] < rec[mid][0] || point[i][0] > rec[mid][2] || point[i][1] < rec[mid][1] || point[i][1] > rec[mid][3]) r = mid;
			else l = mid + 1;
		}
		// debug(i);debug(l);cout << endl;
		bool f = 0;
		if(point[i][0] < rec[l][0] || point[i][0] > rec[l][2] || point[i][1] < rec[l][1] || point[i][1] > rec[l][3]) f = 1;
		if(f){
			if(l % 2 == 1) ans1 ++;
			else ans2 ++;			
		}
	}
	cout << ans1 << " " << ans2 << endl;
}

int main(){
	int tt;
	cin >> tt;
	while(tt -- ){
		solve();
	}
	return 0;
}

G.Money Buys Less Happiness Now

  • 思路:反悔贪心典题,记得是leetcode原题,大根堆维护即可

  • 代码:

    #include <bits/stdc++.h>
    #define int long long
    #define debug(x) cout <<#x <<" = " <<x << endl;
    using namespace std;
    
    int n, x, a[200010];
    
    void solve(){
    	cin >> n >> x;
    	for(int i = 1; i <= n; i ++ ) cin >> a[i];
    	priority_queue<int>q;
    	int s = 0;
    	for(int i = 1; i <= n; i ++ ){
    		q.push(a[i]);
    		s -= a[i];
    		if(s < 0){
    			s += q.top();
    			q.pop();
    		}
    		s += x;
    	}
    	cout << q.size() << endl;
    }
    
    signed main(){
    	int tt;
    	cin >> tt;
    	while(tt -- ){
    		solve();
    	}
    	return 0;
    }
    
  • 16
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值