AtCoder Beginner Contest 338

前面两道阅读理解直接跳过。

C - Leftover Recipes

大意

给定序列Q,A,B和以下不等式组,求\max(x+y)

xA_1+yB_1 \le Q_1

xA_2+yB_2 \le Q_2

\cdots

xA_n+yB_n \le Q_n

思路

N \le 10,可以直接枚举xy,这里我们枚举x

为了确定上界,我们可以设y=0,求出\max(x)

然后直接枚举所有情况即可。

代码

#include<iostream>
#include<vector>
using namespace std;
const int INF = 0x3f3f3f3f;
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);

    int n;
    cin >> n;
    vector<int> q(n), a(n), b(n);
    for(auto &x: q) cin >> x;
    for(auto &x: a) cin >> x;
    for(auto &x: b) cin >> x;

    int max_boundary = INF;
    for(int i = 0; i < n; i++)
        if(a[i]) max_boundary = min(max_boundary, q[i] / a[i]);
    
    int ans = 0;
    for(int A = 0, B; A <= max_boundary; A++){
        B = INF;
        for(int i = 0; i < n; i++)
            if(b[i]) B = min(B, q[i] / b[i]);
        ans = max(ans, A + B);
        for (int i = 0; i < n; i++) q[i] -= a[i];
    }
    cout << ans << endl;
    return 0;
}

D - Island Tour

大意

给定一个n个点的,现在要依次访问点v_1,v_2,\cdots,v_m(可以经过要访问的点以外的点)

现问删去一条边,求依次访问这些点的距离(边数和)的最小值

思路

xy两条路,分别为x,x+1,x+2,\cdots,yx,x-1,x-2,...,y

q_i为删除边<i, i \mod n + 1>的答案。

如果走绿色路径,那么红色路径上的边都可以删,所以q_{x-1},q_{x-2},\cdots,q_y加上绿色路径的长度。

同理,如果走红色路径,那么绿色路径上的边都可以删,所以q_x,q_{x+1},q_{x+2},\cdots,q_y加上红色路径的长度。

但是这么做太慢了,需要差分优化。

代码

#include <iostream>
#include <vector>
#define int long long
using namespace std;

signed main() {
    int n, m, ans = 1e18;
    cin >> n >> m;
    
    vector<int> a(m + 10, 0), c(n + 10, 0);

    auto add = [&](int l, int r, int d){
        c[l] += d;
        c[r + 1] -= d;
    };

    for (int i = 1; i <= m; i++) cin >> a[i];
    for (int i = 1; i < m; i++) {
        int x = a[i], y = a[i + 1];
        if (x > y) swap(x, y);
        int d = y - x;
        add(1, x - 1, d);
        add(x, y - 1, n - d);
        add(y, n, d);
    };
    for (int i = 1; i <= n; i++) c[i] += c[i - 1], ans = min(ans, c[i]);
    cout << ans << endl;
    return 0;
}

E - Chords

大意

有 2n个点等距离地分布在一个圆上,从一个点开始顺时针以 12n编号。

给定n条弦,判断弦之间是否有交点

思路

这里给出一种简单的做法。

把圆拉直,那么弦就会形成若干个区间,显然若两个区间包含或没有交点,则图上这两条弦就没有相交

使用类似括号匹配的做法即可,如果可以匹配,那弦之间就没有交点

代码

#include<iostream>
#include<stack>
#include<vector>
using namespace std;
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);

    int n;
    cin >> n;
    vector<int> a(2 * n + 5, 0);
    stack<int> stk;
    for(int i = 1; i <= n; i++){
        int x, y;
        cin >> x >> y;
        a[x] = a[y] = i;
    }
    for(int i = 1; i <= 2 * n; i++){
        if(stk.empty() || stk.top() != a[i]) stk.push(a[i]);
        else stk.pop();
    }
    cout << (stk.size()? "Yes": "No") << endl;
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值