codeforces round946 div3

A phone desktop

问题:

思路:贪心,先排2x2 再排1x1,2x2的数量决定了ans的下限,1x1的数量决定了上限,最后输出两个值的max

代码:

#include <iostream>

using namespace std;

int a, b;

void solve() {
    cin >> b >> a;
    cout << max((a + 1) / 2, (b + a * 4 + 14) / 15) << endl;
}

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

B Symmetric Encoding

问题:

思路:将给定字符串排序去重,映射回去即可

代码:

#include <iostream>
#include <vector> 
#include <algorithm>

using namespace std;

const int N = 2e5 + 10;

char str[N];
int n;

void solve() {
    cin >> n;
    vector<char> a;
    for(int i = 1; i <= n; i ++ ) {
        cin >> str[i];
        a.push_back(str[i]);
    }
    sort(a.begin(), a.end());
    a.erase(unique(a.begin(), a.end()), a.end());

    int s = a.size() - 1;
    for(int i = 1; i <= n; i ++ ) {
        char c = str[i];
        int pos = 0;
        for(int j = 0; j <= s; j ++ ) {
            if(a[j] == c) {
                pos = j;
                break;
            }
        }
        cout << a[s - pos];
    }
    cout << endl;
}

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

C Beautiful Triple Pairs

问题:

思路:容斥原理

代码:

#include <iostream>
#include <map>

using namespace std;

const int N = 2e5 + 10;

int a[N];
int n;

void solve() {
    cin >> n;
    for(int i = 1; i <= n; i ++ ) cin >> a[i];

    long long ans = 0;

    for(int i = 0; i < 3; i ++ ) {
        for(int j = i + 1; j < 3; j ++ ) {
            map<pair<int, int>, int> ma; 
            for(int k = 1; k <= n - 2; k ++ ) {
                ans += ma[{a[k + i], a[k + j]}]; 
                ma[{a[k + i], a[k + j]}] ++;     
            }
        }
    }

    map<tuple<int, int, int>, int> ma;
    for(int i = 1; i <= n - 2; i ++ ) {
        ans -= 3 * ma[{a[i], a[i + 1], a[i + 2]}];
        ma[{a[i], a[i + 1], a[i + 2]}] ++;
    }

    cout << ans << endl; 
}

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

D ingenuity - 2

问题:

思路:分别考虑竖直方向水平方向,以水平方向为例,出现ew可以抵消,若最后剩下的e或者w为偶数个则合法,另外还要判断H,R是否执行了至少一条指令例如WE这个条件是非法的,原因是肯定有一个机器无法执行命令。这里代码写的很繁琐,写完比赛就结束了,抽时间改一下

代码:

#include <iostream>
#include <vector>
#include <map>

using namespace std;

const int N = 2e5 + 10;

int n;
char str[N];

void solve() {
    map<char, int> ma;
    cin >> n;
    vector<char> ans(n + 1, 'q');
    for(int i = 1; i <= n; i ++ ) {
        cin >> str[i];
        ma[str[i]] ++;
    }
    
    char maxc1, minc1, maxc2, minc2;
    if(ma['N'] > ma['S']) {
        maxc1 = 'N';
        minc1 = 'S';
    } else {
        maxc1 = 'S';
        minc1 = 'N';
    }
    
    if(ma['E'] > ma['W']) {
        maxc2 = 'E';
        minc2 = 'W';
    } else {
        maxc2 = 'W';
        minc2 = 'E';
    }
    
    if((ma[maxc1] - ma[minc1]) % 2 || (ma[maxc2] - ma[minc2]) % 2) {
        cout << "NO" << endl;
        return;
    }//方案不合法
    
    if(ma[maxc1] == ma[minc1] && ma[maxc2] == ma[minc2] && ma[minc1] + ma[minc2] <= 1) {
        cout << "NO" << endl;
        return;
    }
    
    int cntmaxc1 = ma[minc1] + (ma[maxc1] - ma[minc1]) / 2;
    int cntmaxc2 = ma[minc2] + (ma[maxc2] - ma[minc2]) / 2;
    
    bool flag = true;
    if(flag && ma[maxc1] == ma[minc1] && ma[maxc1] != 0) {
       // cntmaxc1 --;
        bool flagma = 1, flagmin = 1;
        for(int i = 1; i <= n; i ++ ) {
            if(flagma && str[i] == maxc1) {
                ans[i] = 'H';
                flagma = 0;
            }
            
            if(flagmin && str[i] == minc1) {
                ans[i] = 'H';
                flagmin = 0;
            }
        }
        flag = false;
    }
    
    if(flag && ma[maxc2] == ma[minc2] && ma[maxc2] != 0) {
        //cntmaxc2 --;
        bool flagma = true, flagmin = true;
        for(int i = 1; i <= n; i ++ ) {
            if(flagma && (str[i] == maxc2)) {
                ans[i] = 'H';
                flagma = false;
            }
            
            if(flagmin && str[i] == minc2) {
                ans[i] = 'H';
                flagmin = false;
            }
        }
        flag = false;
    } 
    
    if(flag && ma[maxc1] != ma[minc1]) {
        //cntmaxc1 --;
        for(int i = 1; i <= n; i ++ ) {
            if(str[i] == maxc1) {
                ans[i] = 'H';
                break;
            }
        }
        flag = false;
    }
    
    if(flag && ma[maxc2] != ma[minc2]) {
        //cntmaxc2 --;
        for(int i = 1; i <= n; i ++ ) {
            if(str[i] == maxc2) {
                ans[i] = 'H';
                break;
            }
        }
        flag = false;
    }
    
    for(int i = 1; i <= n; i ++ ) {
        if(ans[i] == 'q') {
            if(str[i] == 'N' || str[i] == 'S') {
                if(str[i] == minc1) {
                    ans[i] = 'R';
                } else {
                    if(cntmaxc1) {
                        cntmaxc1 --;
                        ans[i] = 'R';
                    } else ans[i] = 'H';
                }
            } else {
                if(str[i] == minc2) {
                    ans[i] = 'R';
                } else {
                    if(cntmaxc2) {
                        cntmaxc2 --;
                        ans[i] = 'R';
                    } else ans[i] = 'H';
                }
            }
        }
    }

    for(int i = 1; i <= n; i ++ ) cout << ans[i];
    cout << endl;
    /*cout << ma['W'] << " " << ma['E'];
    cout << maxc2 << minc2;*/
}

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

E money buy less happy

问题:

思路:背包,dp[i]表示当前happy值为i,可以拥有的最大钱数,从大到小枚举是为了让状态转移时用已经搜过的状态转移,最开始把不可能的状态置负无穷dp[0]置0,这样搜出来的方案一定是可以实现的,dp时每个月记得加上工资

代码:

#include <iostream>
#include <vector>
 
using namespace std;
 
const int N = 55;
 
int n, x;
int cost[N], happy[N];
 
void solve() {
    cin >> n >> x;
    int sum = 0;
    for(int i = 1; i <= n; i ++ ) {
        cin >> cost[i] >> happy[i];
        sum += happy[i];
    }
 
    vector<long long> dp(sum + 1, -1e17);
    dp[0] = 0;
    
    for(int day = 1; day <= n; day ++ ) {
        for(int i = sum; i >= 0; i -- ) {
            if((i - happy[day] >= 0) && (dp[i - happy[day]] - cost[day] >= 0)) {
                dp[i] = max(dp[i], dp[i - happy[day]] - cost[day]);
            }
            dp[i] += x;//工资
        }
    }
    
    for(int i = sum; i >= 0; i -- ) 
        if(dp[i] >= 0) {
            cout << i << endl;
            return;
        }
}
 
int main() {
    int t;
    cin >> t;
    while(t -- ) {
        solve();
    }
}

F cutting game

题目:

思路:思路源于b站幻想家协会会长,离线做法+二维二分,对二分的顶级理解,这是我目前为止看到的最简洁的做法

代码:

#include <iostream>

using namespace std;

const int N = 2e5 + 10;

int a, b, n, m;
struct node{
    int x1, y1, x2, y2;
}d[N];
pair<int, int> pos[N];

void solve() {
    cin >> a >> b >> n >> m;
    for(int i = 1; i <= n; i ++ ) {
        int x, y;
        cin >> x >> y;
        pos[i] = {x, y};
    }
    int x1, y1, x2, y2;
    x1 = 1, y1 = 1, x2 = a, y2 = b;
    //cout << x1 << " " << y1 << " " << x2 << " " << y2 << endl;
    for(int i = 1; i <= m; i ++ ) {
        char op;
        int x;
        cin >> op >> x;
        if(op == 'U') {
            x1 += x;
            d[i] = {x1, y1, x2, y2};
        } else if(op == 'D') {
            x2 -= x;
            d[i] = {x1, y1, x2, y2}; 
        } else if(op == 'L') {
            y1 += x;
            d[i] = {x1, y1, x2, y2}; 
        } else {
            y2 -= x;
            d[i] = {x1, y1, x2, y2}; 
        }
    }
    
    int scoreA = 0, scoreB = 0;
    for(int i = 1; i <= n; i ++ ) {
        int x = pos[i].first, y = pos[i].second;
        int l = 1, r = m + 1;
        while(l < r) {
            int mid = l + r >> 1;
            if(x < d[mid].x1 || x > d[mid].x2 || y < d[mid].y1 || y > d[mid].y2) r = mid;
            else l = mid + 1;
        }
        if(l != m + 1) {
            if(l & 1) scoreA ++;
            else scoreB ++;
        }
    }
    cout << scoreA << " " << scoreB << endl;
}

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

G money buys less happiness now

问题:

思路:贪心。

代码:

#include <iostream>
#include <queue>

using namespace std;

const int N = 2e5 + 10;

int m, x;
int cost[N];

void solve() {
    priority_queue<int> q;
    cin >> m >> x;
    for(int i = 1; i <= m; i ++ ) cin >> cost[i];
    long long salary = 0;
    for(int i = 1; i <= m; i ++ ) {
        q.push(cost[i]);
        salary -= cost[i];
        while(salary < 0) {
            salary += q.top();
            q.pop();
        }
        salary += x;
    }
    cout << q.size() << endl;
}

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值