Codeforces Round #610 (Div. 2) 简要题解

http://codeforces.com/contest/1282
坚持下去谁也不知道结果是什么,但不坚持我肯定会后悔的。

这场比赛自闭了,对我极其不友好,读不懂,读懂了又做不来。

A.Temporarily unavailable

题意:给一个区间[a,b],以及一个基站c,以及信号覆盖范围半径r,一个人以单位速度从a到b运动,问过程中有多少时间不再基站信号范围内。
做法:直接模拟即可,求出信号的区间,与原来的区间相比即可。

//#include <iostream>
//#include <algorithm>
//#include <stdio.h>
//#include <string.h>
//#include <vector>
//#include <math.h>
#include "bits/stdc++.h"
 
using namespace std;
 
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
//#define ls(x) tr[x].ls
//#define rs(x) tr[x].rs
//#define lowbit(x) x&-x
 
const int inf = 0x3f3f3f3f;
const int maxn = 200000 + 10;
typedef long long ll;
 
void solve() {
    ll a, b, c, r;
    cin >> a >> b >> c >> r;
    if (a > b) swap(a, b);
    int la = c - r;
    int lb = c + r;
    ll ans = 0;
    if (la <= a && lb >= b) {
        cout << 0 << endl;
        return;
    }
    if (la >= a && la <= b) ans += la - a;
    if (lb <= b && lb >= a) ans += b - lb;
    if (ans == 0) ans = b - a;
    cout << ans << endl;
}
 
int main() {
    int T;
    cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}

B - K for the Price of One

这道题自闭的开始。题目又长,英文又不好,不想看,他们口嗨了一句,k个优惠只能用一次。我居然当真了,然后WA了,后来又看见必须要有k个才能用。。。然后就写了假算法,最后知道题意,想了个dp,想太复杂了放弃了,跟着它们乱搞了一个二分答案过去了?????…
题意:给你n个物品的价值,以及你拥有的钱,如果你能买任意k个中最贵的那一个,那么另外k-1个免费获得。问最多能得到多少个。
做法:其实不复杂的,首先排一个序,我们想象一个状态d[i]表示前i个都买了最少花费。
那么就可以这样递推 d [ i ] = a [ i ] + ( i > = k ) ? s [ i k ] : s [ i 1 ] d[i]=a[i]+(i>=k)?s[i-k]:s[i-1]
然后遍历答案就可以了,因为假设你最多能买x个,那么这x个一定是前x个。

//#include <iostream>
//#include <algorithm>
//#include <stdio.h>
//#include <string.h>
//#include <vector>
//#include <math.h>
#include "bits/stdc++.h"
 
using namespace std;
 
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
//#define ls(x) tr[x].ls
//#define rs(x) tr[x].rs
//#define lowbit(x) x&-x
 
const int inf = 0x3f3f3f3f;
const int maxn = 200000 + 10;
typedef long long ll;
ll n, p, k, a[maxn], s[maxn];
void solve() {
    cin >> n >> p >> k;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    sort(a + 1, a + n + 1);
    int ans = 0;
    s[0] = 0;
    for (int i = 1; i <= n; i++) {
        if (i < k) s[i] = s[i - 1] + a[i];
        else s[i] = s[i - k] + a[i];
        if (s[i] <= p) ans = i;
    }
    cout << ans << endl;
}
 
int main() {
    int T;
    cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}

C - Petya and Exam

这道题原谅我英语水平不好。照着翻译看了半天才看懂。
题意:给出题目中所说的人解决一个困难和简单问题所需要的时间,以及总时间和题目的数量以及难度。最后给出每个题目变成"强制性"的时间,如果到了题目变成了强制性没有完成任何一道强制性题目,都会得零分,当然你可以提前离场。问最多能得多少分,一个题目一分。
做法:按照变成强制性的时间从小到大进行排序,记录先前变成强制性题目的数量,并与ti-1进行比较如果过大就零分,过小就优先解决后面的简单的问题,然后更新答案。这样贪心即可。

//#include <iostream>
//#include <algorithm>
//#include <stdio.h>
//#include <string.h>
//#include <vector>
//#include <math.h>
#include "bits/stdc++.h"
 
using namespace std;
 
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
//#define ls(x) tr[x].ls
//#define rs(x) tr[x].rs
//#define lowbit(x) x&-x
 
const int inf = 0x3f3f3f3f;
const int maxn = 200000 + 10;
typedef long long ll;
struct node {
    int f;
    ll t;
} p[maxn];
bool cmp(node a, node b) { return a.t < b.t; }
 
int n;
ll t, a, b;
void solve() {
    cin >> n >> t >> a >> b;
    int cnta = 0, cntb = 0;
    for (int i = 1; i <= n; i++) {
        cin >> p[i].f;
        if (p[i].f) cntb++;
        else cnta++;
    }
    for (int i = 1; i <= n; i++) cin >> p[i].t;
    sort(p + 1, p + n + 1, cmp);
    p[n + 1].t = t + 1;
    ll ans = 0, c1 = 0, c2 = 0;
    for (int i = 1; i <= n + 1; i++) {
        ll tmp = c1 * a + c2 * b;
        ll time = p[i].t - 1 - tmp;
        if (time >= 0) {
            ll ta = min(time / a, cnta - c1);
            time -= ta * a;
            ll tb = min(time / b, cntb - c2);
            ans = max(ans, ta + tb + c1 + c2);
        }
        if (p[i].f) c2++;
        else c1++;
    }
    cout << ans << endl;
}
 
int main() {
    int T;
    cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}

D - Enchanted Artifact

这是一个交互式问题
又是照着翻译看的
题意:后台有一个字符串长度为n,只由ab组成,你可通过最多n+2次询问,尝试得出字符串。每次你可以输出一个字符串,如果字符串完全匹配,则结束程序,否则给出不同的价值,这个价值表示其中一个字符串需要删除,变换多少次。
做法:首先用定义两个最长的全a和全b字符串,然后询问两次,这样可以判断字符串长度n,然后就可以挨着一位一位的判断了,最坏情况下刚刚n+2次。

//#include <iostream>
//#include <algorithm>
//#include <stdio.h>
//#include <string.h>
//#include <vector>
//#include <math.h>
#include "bits/stdc++.h"
 
using namespace std;
 
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
//#define ls(x) tr[x].ls
//#define rs(x) tr[x].rs
//#define lowbit(x) x&-x
 
const int inf = 0x3f3f3f3f;
const int maxn = 200000 + 10;
typedef long long ll;
 
int query(string s) {
    cout << s << endl;
    int ans;
    cin >> ans;
    if (ans <= 0) exit(0);
    return ans;
}
 
int main() {
    string s1, s2;
    for (int i = 0; i < 300; i++)
        s1 += 'a', s2 += 'b';
    int na = 300 - query(s1);
    int nb = 300 - query(s2);
    int n = na + nb;
    string ans;
    for (int i = 0; i < n; i++) ans += 'a';
    if (nb == 0) {
        query(ans);
    }
    int tmp = nb;
    for (int i = 0; i < n; i++) {
        ans[i] = 'b';
        int xx = query(ans);
        if (xx > tmp) {
            ans[i] = 'a';
        } else {
            tmp = xx;
        }
    }
    return 0;
}

E - The Cake Is a Lie

还是照着翻译看的
题意:给出一个n个点凸多边形,顶点用1-n随便编号,现在把他切成n-2个三角形,任意乱序给出n-2个三角形,尝试求出 顶点顺时针或者逆时针的编号并且任意起点都可以,以及三角形的切出顺序,任意一个即可。
做法:其实这题我是不怎么会的,题解也没有看懂。但不过看了一位大佬的代码,忽然好像就知道了。首先我们先考虑顶点编号,我们发现一条边最多会使用两次,对于只使用了一次的边肯定就是凸包的边了。我们考虑使用 x o r xor 运算来解决这个问题,对于给出的三角形首先进行 对边用map进行标记记录下共用的三角形的标号,同时对顶点进行异或,如果是共用边,一个顶点异或两次没有影响,然后在map中找到任意一条只使用了一次的边的两个顶点,然后就可以用 x o r xor 进行类似链表的操作得到答案。关于三角形的顺序这个我倒是想到了,共用边的两个三角形,建立一个无向图,然后dfs,从叶子向上输出就可以了。

//#include <iostream>
//#include <algorithm>
//#include <stdio.h>
//#include <string.h>
//#include <vector>
//#include <math.h>
#include "bits/stdc++.h"
 
using namespace std;
 
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
//#define ls(x) tr[x].ls
//#define rs(x) tr[x].rs
//#define lowbit(x) x&-x
 
const int inf = 0x3f3f3f3f;
const int maxn = 200000 + 10;
typedef long long ll;
map<pair<int, int>, vector<int> > mp;
vector<int> p[maxn];
int n, a, b, c, v[maxn], vis[maxn];
vector<int> pp;
 
void dfs(int u, int f) {
    for (auto v:p[u]) {
        if (v == f) continue;
        dfs(v, u);
    }
    cout << u << ' ';
}
 
void solve() {
    mp.clear();
 
    cin >> n;
    for (int i = 0; i <= n + 1; i++) {
        v[i] = 0;
        p[i].clear();
    }
 
    for (int i = 1; i <= n - 2; i++) {
        cin >> a >> b >> c;
        if (a > b) swap(a, b);
        if (b > c) swap(b, c);
        if (a > b) swap(a, b);
        v[a] ^= b, v[a] ^= c;
        v[b] ^= a, v[b] ^= c;
        v[c] ^= b, v[c] ^= a;
        mp[{a, b}].push_back(i);
        mp[{b, c}].push_back(i);
        mp[{a, c}].push_back(i);
    }
    for (auto H:mp) {
        if (H.second.size() == 1) {
            a = H.first.first;
            b = H.first.second;
            break;
        }
    }
    cout << a << ' ' << b << ' ';
    for (int i = 0; i < n - 2; i++, swap(a, b)) cout << (a ^= v[b]) << ' ';
    cout << endl;
    for (auto H:mp) {
        if (H.second.size() == 2) {
            p[H.second[0]].push_back(H.second[1]);
            p[H.second[1]].push_back(H.second[0]);
        }
    }
    dfs(1, 0);
//    cout << pp.size() << endl;
//    for (auto x:pp) {
//        cout << x << " ";
//    }
    cout << endl;
}
 
int main() {
    int T;
    cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}
发布了130 篇原创文章 · 获赞 80 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/KXL5180/article/details/103698558