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] j−h[i]的剩余的值是大于等于c[i]的,就可以转移过来,剩下的钱就是 d p [ j − h [ i ] ] − c [ i ] dp[j - h[i]] - c[i] dp[j−h[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; }