Codeforces Round #675 (Div. 2) ABCDE

A

直接最长边

相当于等腰梯形

#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;
 
template<class T1, class T2> bool umin(T1& a, T2 b) { return a > b ? (a = b, true) : false; }
template<class T1, class T2> bool umax(T1& a, T2 b) { return a < b ? (a = b, true) : false; }
template<class T> void clear(T& a) { T().swap(a); }
 
const int N = 1e5 + 5;
 
int n, m, _, k;
int a[4];
 
int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> a[1] >> a[2] >> a[3];
        sort(a + 1, a + 1 + 3);
        cout << a[3] << '\n';
    }
    return 0;
}

B

找就行了

#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;
 
template<class T1, class T2> bool umin(T1& a, T2 b) { return a > b ? (a = b, true) : false; }
template<class T1, class T2> bool umax(T1& a, T2 b) { return a < b ? (a = b, true) : false; }
template<class T> void clear(T& a) { T().swap(a); }
 
const int N = 1e5 + 5;
 
int n, m, _, k;
ll a[105][105], b[5];
 
int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> n >> m; ll ans = 0;
        rep (i, 1, n) rep (j, 1, m) cin >> a[i][j];
        rep (i, 1, n + 1 >> 1)
            rep (j, 1, m + 1 >> 1) {
                if (i == n - i + 1 && j == m - j + 1) continue;
                if (i == n - i + 1) { ans += abs(a[i][j] - a[i][m - j + 1]); continue; }
                if (j == m - j + 1) { ans += abs(a[i][j] - a[n - i + 1][j]); continue; }
                b[1] = a[i][j]; b[2] = a[i][m - j + 1];
                b[3] = a[n - i + 1][j]; b[4] = a[n - i + 1][m - j + 1];
                ll mi = 2e18;
                rep (p, 1, 4) {
                    ll res = 0;
                    rep (q, 1, 4) res += abs(b[p] - b[q]);
                    umin(mi, res); 
                }
                ans += mi;
            }
        cout << ans << '\n';
    }
    return 0;
}

C

自闭了, 挂机了1h+, 掉分了≡(▔﹏▔)≡

对于每一位, 分别计算就行了, 看看代码就明白了

#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;
 
template<class T1, class T2> bool umin(T1& a, T2 b) { return a > b ? (a = b, true) : false; }
template<class T1, class T2> bool umax(T1& a, T2 b) { return a < b ? (a = b, true) : false; }
template<class T> void clear(T& a) { T().swap(a); }
 
const int N = 1e5 + 5, mod = 1e9 + 7;
 
int n, m, _, k;
ll sum[N], a[N], t[N] = {1};
char s[N];
 
int main() {
    IOS; cin >> s + 1; n = strlen(s + 1);
    rep(i, 1, 1e5) {
        t[i] = t[i - 1] * 10 % mod;
        a[i] = (a[i - 1] + i) % mod;
        sum[i] = i * t[i - 1] % mod;
        sum[i] = (sum[i - 1] + sum[i]) % mod;
    }
    ll ans = 0;
    per(i, n, 1) {
        ans = (ans + (s[i] ^ 48) * sum[n - i] % mod) % mod;
        ans = (ans + (s[i] ^ 48) * a[i - 1] % mod * t[n - i]) % mod;
    }
    cout << ans;
    return 0;
}

D

最短路, 当然你 m * m建边必t

要贪心的去建边

对于 传送站 i\((x_i), y_i\), j\((x_j, y _j)\) \((x_i <= x_j)\)

距离则为min(abs(\(x_i - x_j\)), (\(y_i, y_j\)))

假设 abs(\(x_i - x_j\)) <= (\(y_i, y_j\)), 存在传送站 k(\(x_k, y_k\)) 且(\(y_k == y_i\) && (\(x_i <= x_k <= x_j\))), 那么i和j的距离可能会更新(最少不会增加)

所以我们应该直接先去找这样的 k, 就有了 (i,k) (k, j) 建边而不是 三个传送站两两建边, 建边就被优化了

#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;
 
template<class T1, class T2> bool umin(T1& a, T2 b) { return a > b ? (a = b, true) : false; }
template<class T1, class T2> bool umax(T1& a, T2 b) { return a < b ? (a = b, true) : false; }
template<class T> void clear(T& a) { T().swap(a); }
 
const int N = 1e5 + 5, mod = 1e9 + 7;
const ll inf64 = 1e18;
 
int n, m, _, k;
 
int main() {
    IOS; cin >> n >> m;
    vector<ll[2]> pos(m + 2);
    cin >> pos[m][0] >> pos[m][1] >> pos[m + 1][0] >> pos[m + 1][1];
    rep(i, 0, m - 1) cin >> pos[i][0] >> pos[i][1];
 
    vector<vector<pair<ll, int>>> e(m + 2);
    rep(i, 0, m) e[i].pb({ abs(pos[i][0] - pos[m + 1][0]) + abs(pos[i][1] - pos[m + 1][1]), m + 1 });
 
    rep(k, 0, 1) {
        vector<pair<ll, int>> a(m + 1);
        rep(i, 0, m) a[i] = { pos[i][k], i };
        sort(all(a));
        rep(i, 1, m) {
            ll d = a[i].fi - a[i - 1].fi;
            int x = a[i].se, y = a[i - 1].se;
            e[x].pb({ d, y }); e[y].pb({ d, x });
        }
    }
 
    vector<bool> v(m + 2); vector<ll> d(m + 2, inf64); d[m] = 0;
    priority_queue<pair<ll, int>> q; q.push({ -0, m });
    while (!q.empty()) {
        int x = q.top().se; q.pop();
        if (v[x]) continue; v[x] = 1;
        for (auto& i : e[x]) {
            int y = i.se; ll w = i.fi;
            if (d[y] <= d[x] + w) continue;
            d[y] = d[x] + w;
            q.push({ -d[y], y });
        }
    }
    cout << d[m + 1] << '\n';
    return 0;
}

E

先看清题是最重要的, 是选择 s[i] == s[i + 1] 的删掉, 一次性, 不会因为删除 i, i + 1之后 i + 2 就会变成 i, (wa46)

因为要求最小字典序, 所以倒着求(只有这样, 在 i 处, i + 1~n 的序列是确定的, 才能和 i + 2~n 的后缀比大小)

维护一下 ne[i], 大于节点i 且 s[ne[i]] != s[i] 的最小值 (用来比大小)

同时我们还要维护一个 当前最近, 次近(用来在 最近被删除时 得到新的最近未被删除)未被删除的节点下标

为什么不能用 ne[i] 存呢?

cxxxzzxca

对于 (从0开始) ne[1] = 7(最近未被删除是 s[6] == 'x')

到了 i == 0, s[ne[i + 1] = 7] == s[i], ne[i] = ne[ne[i + 1]] = 8

然而真正的 ne[i = 0] = 6 (s[6] == 'x'), 这就是我wa了半天 47 的地方

int a, b, len[N], lens, ne[N];
string s, ans[N], cur;
 
void solve(int x) {
    cur += s[x];
    if (s[x] != s[a]) ne[x] = a;
    else ne[x] = ne[a];
    b = a; a = x; 
    len[x] = cur.size();
    if (cur.size() <= 10) ans[x] = cur, reverse(all(ans[x]));
    else {
        string t = cur.substr(cur.size() - 5, 5); reverse(all(t));
        ans[x] = t + "..." + cur[1] + cur[0];
    }
}
 
int main() {
    IOS; cin >> s; a = lens = s.size();
    s += char(0); ne[lens] = lens; 
    per(i, lens - 1, 0) {
        if (s[i] != s[i + 1]) solve(i);
        else if (i + 1 == a && s[ne[i + 1]] < s[i]) {
            a = b; cur.pop_back();
            len[i] = len[i + 2]; ans[i] = ans[i + 2];
        }
        else solve(i);
    }
    rep(i, 0, lens - 1) cout << len[i] << ' ' << ans[i] << '\n';
    return 0;
}
posted @ 2020-10-05 18:32  洛绫璃  阅读(341)  评论(0编辑  收藏  举报