ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

AtCoder Beginner Contest 223 复盘

2021-10-18 08:33:31  阅读:185  来源: 互联网

标签:AtCoder return Beginner int Segt mid MAXN Query 223


打得很烂,预计 1500 只拿到了 700,甚至比 VP 打得还要差。

A

一遍 AC。

int main() {
    int x = read();
    if (x % 100 == 0 && x > 0) puts("Yes");
    else puts("No");
    return 0;
}

B

一遍 AC。

const int MAXN = 2000 + 10;

std::string ss;
std::string strs[MAXN];

int main() {
    cin >> ss;
    strs[1] = ss;
    for (int i = 2; i <= ss.length(); ++i) {
        strs[i] = strs[i - 1];
        char last = strs[i][0];
        strs[i].erase(strs[i].begin());
        strs[i] += last;
    }
    std::sort(strs + 1, strs + 1 + ss.length());
    cout << strs[1] << endl;
    cout << strs[ss.length()] << endl;
    return 0;
}

C. Doukasen

垃圾解方程题,我被卡在第三个样例上了,没调出来,换了题解的写法才过。

其实这种解方程题并不用非得去找到特定位置然后列数据解方程,可以直接去把等式的值求出来,然后用这个值去求解,比如这个题的方程就是 \(\mathrm{ltime} + \frac{x}{B} = \mathrm{rtime} + \frac{A - x}{B}\),等式的意义是两边烧的时间相等(都是 \(\frac{1}{2}\sum\frac{A}{B}\),于是可以直接求这个东西,再带回原式求解。

const int MAXN = 1e5 + 10;

int n;
double aa[MAXN], bb[MAXN];
double burntime[MAXN];
double prefix[MAXN], suffix[MAXN];

int main() {
    n = read();
    for (int i = 1; i <= n; ++i){
        aa[i] = read(); bb[i] = read();
        burntime[i] = (double) aa[i] /(double) bb[i];
    }
    for (int i = 1; i <= n; ++i) {
        prefix[i] = prefix[i - 1] + burntime[i];
    }
    double len = 0;
    double tim = prefix[n] / 2.0;
    rep (i, 1, n) {
        if (prefix[i] > tim) {
            double dt = tim - prefix[i - 1];
            len += bb[i] * dt;
            printf("%.6lf\n", len);
            return 0;
        }
        len += aa[i];
    }
    return 0;
}

D. Restricted Permutation

第一眼看过去和《菜肴制作》差不多,其实还有些不一样,令最小的最靠前和令字典序最小这两个是不同的,前者需要建反图反着跑,后者建正图就可以了。核心思想都是利用优先队列代替普通队列。

const int MAXN = 2e5 + 10;

int n, m;

std::vector<int> G[MAXN];
int ind[MAXN];

int main() {
    n = read(); m = read();
    rep (i, 1, m) {
        int u = read(); int v = read();
        G[u].push_back(v);
        ++ind[v];
    }
    std::vector<int> ord;
    std::priority_queue<int, std::vector<int>, std::greater<int> > q;
    for (int i = 1; i <= n; ++i) {
        if (!ind[i]) {
            q.push(i);
        }
    }
    while (!q.empty()) {
        int u = q.top(); q.pop();
        ord.push_back(u);
        std::sort(ALL(G[u]));
        forall (G[u], i) {
            int v = G[u][i];
            --ind[v];
            if (!ind[v]) {
                q.push(v);
            }
        }
    }
    if (ord.size() != n) printf("-1");
    else for (auto v : ord) printf("%d ", v);
    puts("");
    return 0;
}

F. Parenthesis Checking

也是套路了,把左括号看成 \(+1\) 右括号看成 \(-1\),一个括号串合法等价于整个串的和为 \(0\) 且中间没有掉到负数(相对值),所以需要对原序列维护一个区间和,前缀和的最小值,后面这个东西有点反直觉但是也能直接维护。

考场上我懒得去费劲想这个东西了,所以我选择用线段树维护前缀和数组,一次操作等价于修改两个后缀 \([l, n]\) 和 \([r, n]\),查询就是查 \(r\) 和 \(l - 1\) 两个点的值和 \(l\) 到 \(r\) 的区间最小值。

然后区间最值写挂了,调一场没调出来。

#错误警示:想清楚区间修改到底是怎么修改的。基础题不要写错。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>

#define forall(G,i) for (int i = 0, __for_siz__ = (int) (G).size(); i < __for_siz__; ++i)
#define DEBUG(x) std::cerr << #x << " = " << x << endl;
#define rep(i_,a_,b_) for (int i_ = (a_); (i_) <= (b_); (i_) = (i_) + 1)
#define ALL(x) (x).begin(), (x).end()
#define MP std::make_pair
#define se second
#define endl '\n'
#define fi first

using std::cin;
using std::cout;

typedef long long int lli;

inline int read() {
    int s = 0, x = 1; char ch = getchar();
    while (!isdigit(ch)) { if (ch == '-') x = -x; ch = getchar(); }
    while (isdigit(ch)) { s = s * 10 + ch - '0'; ch = getchar(); }
    return s * x;
}

inline lli readll() {
    lli s = 0, x = 1; char ch = getchar();
    while (!isdigit(ch)) { if (ch == '-') x = -x; ch = getchar(); }
    while (isdigit(ch)) { s = s * 10 + ch - '0'; ch = getchar(); }
    return s * x;
}

const int MAXN = 4e5 + 10;

int n, q;
char ss[MAXN];

namespace Segt {
lli minx[MAXN << 2], sum[MAXN << 2];
lli tag[MAXN << 2];

#define ls (p << 1)
#define rs (p << 1 | 1)

void Update(int p) {
    sum[p] = sum[ls] + sum[rs];
    minx[p] = std::min(minx[ls], minx[rs]);
}
void buildTree(int p, int l, int r, lli *seq) {
    if (l == r) { minx[p] = sum[p] = seq[l]; return;  }
    int mid = (l + r) >> 1;
    buildTree(ls, l, mid, seq); buildTree(rs, mid + 1, r, seq);
    Update(p);
}
void Add(int p, lli l, lli r, lli k) {
    sum[p] += k * (r - l + 1);
    minx[p] += k;
    tag[p] += k;
}
void Pushdown(int p, int l, int r) {
    if (!tag[p]) return;
    int mid = (l + r) >> 1;
    Add(ls, l, mid, tag[p]); Add(rs, mid + 1, r, tag[p]);
    tag[p] = 0;
}
void Modify(int p, int l, int r, int ll, int rr, lli k) {
    if (l == ll && rr == r) { Add(p, l, r, k); return;  }
    int mid = (l + r) >> 1;
    Pushdown(p, l, r);
    if (rr <= mid) Modify(ls, l, mid, ll, rr, k);
    else if (mid + 1 <= ll) Modify(rs, mid + 1, r, ll, rr, k);
    else {
        Modify(ls, l, mid, ll, mid, k);
        Modify(rs, mid + 1, r, mid + 1, rr, k);
    }
    Update(p);
}
std::pair<lli, lli> Query(int p, int l, int r, int ll, int rr) {
    if (rr < 1) return {0, 0};
    if (l == ll && rr == r) return {sum[p], minx[p]};
    Pushdown(p, l, r);
    int mid = (l + r) >> 1;
    if (rr <= mid) return Query(ls, l, mid, ll, rr);
    else if (mid + 1 <= ll) return Query(rs, mid + 1, r, ll, rr);
    else {
        std::pair<lli, lli> lt = Query(ls, l, mid, ll, mid), rt = Query(rs, mid + 1, r, mid + 1, rr);
        return {lt.first + rt.first, std::min(lt.second, rt.second)};
    }
}
}

lli seq[MAXN];

int main() {
    scanf("%d %d", &n, &q);
    scanf("%s", ss + 1);
    rep (i, 1, n) {
        if (ss[i] == '(') seq[i] = 1;
        else seq[i] = -1;
        seq[i] += seq[i - 1];
    }
    Segt::buildTree(1, 1, n, seq);
    while (q --> 0) {
        int pos, l, r; scanf("%d %d %d", &pos, &l, &r);
        if (pos == 1) {
            lli tl = Segt::Query(1, 1, n, l, l).first - Segt::Query(1, 1, n, l - 1, l - 1).first;
            lli tr = Segt::Query(1, 1, n, r, r).first - Segt::Query(1, 1, n, r - 1, r - 1).first;
            Segt::Modify(1, 1, n, l, n, -tl + tr);
            Segt::Modify(1, 1, n, r, n, -tr + tl);
        } else {
            std::pair<lli, lli> fx = Segt::Query(1, 1, n, r, r), pref = Segt::Query(1, 1, n, l - 1, l - 1), px = Segt::Query(1, 1, n, l, r);
            if ((fx.first - pref.first) || (px.second - pref.first)) puts("No");
            else puts("Yes");
        }
    }
    return 0;
}

标签:AtCoder,return,Beginner,int,Segt,mid,MAXN,Query,223
来源: https://www.cnblogs.com/handwer/p/15419059.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有