首页 > 其他分享 >Atcoder Beginner Contest 369

Atcoder Beginner Contest 369

时间:2024-09-01 08:55:31浏览次数:11  
标签:Atcoder return Beginner int long mx 369 id dp

Atcoder Beginner Contest 369

C-Count Arithmetic Subarrays

题意

给出一个长度为 \(n\) 的序列 \(A\),求有多少个 \(A\) 的连续子序列为等差数列。

思路

对于递增的右端点,左端点不减。

使用双指针,枚举右端点,扫描左端点。

时间复杂度:\(O(n)\)。

代码

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 2e5 + 5;
int a[N], n;
ll ans;
void solve() {
    cin >> n;
    for (int i = 1; i <= n; i ++) cin >> a[i];
    for (int i = 1, j = 1; i <= n; i ++) {
        j = max(j, i);
        while (i < n && j < n && a[j + 1] - a[j] == a[i + 1] - a[i]) j ++;
        ans += j - i + 1;
    }
    cout << ans << "\n";
}
int main() {
    int T = 1;
    // cin >> T;
    while (T --) 
        solve();
    return 0;
}

D-Bonus EXP

题意

给出一个长度为 \(n\) 的序列 \(A\),每次有两种选择。

  1. 将得分增加 \(A_i\),若这是第偶数次执行这个操作,将得分额外增加 \(A_i\)。
  2. 什么也不做。

求最大得分。

思路

定义 \(dp_{i,0/1}\) 表示前 \(i\) 个数,做了偶数或奇数次操作 \(1\) 的最大得分。

初始状态 \(dp_{0,0}=0\)。

\(dp_{i,0}\) 转移方程:

\[dp_{i,0}=\max(dp_{i-1,0},dp_{i-1,1}+2\times a_i) \]

\(dp_{i,1}\) 转移方程:

\[dp_{i,1}=\max(dp_{i-1,1},dp_{i-1,0}+a_i) \]

时间复杂度:\(O(n)\)。

代码

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 2e5 + 5;
int n, a[N];
ll dp[N][2];
void solve() {
    cin >> n;
    for (int i = 1; i <= n; i ++) cin >> a[i];
    memset(dp, -0x3f, sizeof(dp));
    dp[0][0] = 0;
    for (int i = 1; i <= n; i ++) {
        dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + a[i]);
        dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + 2 * a[i]); 
    }
    cout << max(dp[n][0], dp[n][1]) << "\n";
}
int main() {
    int T = 1;
    // cin >> T;
    while (T --) 
        solve();
    return 0;
}

E-Sightseeing Tour

题意

给定一张 \(n\) 个点 \(m\) 条边的图,有 \(q\) 次查询。

每次查询给出 \(k\) 条边,求一条 \(1\) 到 \(n\) 并且经过这 \(k\) 条边的最短路径。

思路

先用 Floyd 求出全源最短路,再枚举给出的边的排列,即经过顺序。

搜索从每条边的哪个点进入,在两条边的端点之间走最短路,并加上该边权。

时间复杂度:\(O(n^3+q k!2^k)\)。

代码

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 405, M = 2e5 + 5;
int n, m, q, K, id[N];
ll f[N][N], ans;
int u[M], v[M], w[M];
void dfs(int p, int x, ll cost) {
    if (cost > ans) return ;
    if (x == u[id[p]]) x = v[id[p]];
    else x = u[id[p]];
    cost += w[id[p]];
    if (p == K) {
        cost += f[x][n];
        ans = min(ans, cost);
        return ;
    }
    dfs(p + 1, u[id[p + 1]], cost + f[x][u[id[p + 1]]]);
    dfs(p + 1, v[id[p + 1]], cost + f[x][v[id[p + 1]]]);
}
void solve() {
    cin >> n >> m;
    memset(f, 0x3f, sizeof(f));
    for (int i = 1; i <= m; i ++) {
        cin >> u[i] >> v[i] >> w[i];
        f[u[i]][v[i]] = min(f[u[i]][v[i]], 1ll * w[i]);
        f[v[i]][u[i]] = min(f[v[i]][u[i]], 1ll * w[i]);
    }
    for (int i = 1; i <= n; i ++) f[i][i] = 0;
    for (int k = 1; k <= n; k ++) {
        for (int i = 1; i <= n; i ++) {
            for (int j = 1; j <= n; j ++) {
                f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
            }
        }
    }
    cin >> q;
    for (int i = 1; i <= q; i ++) {
        cin >> K;
        for (int j = 1; j <= K; j ++) cin >> id[j];
        sort(id + 1, id + K + 1);
        ans = 1e18;
        do {
            dfs(1, u[id[1]], f[1][u[id[1]]]);
            dfs(1, v[id[1]], f[1][v[id[1]]]);
        } while(next_permutation(id + 1, id + K + 1));
        cout << ans << "\n";
    }
}
int main() {
    int T = 1;
    // cin >> T;
    while (T --) 
        solve();
    return 0;
}

F-Gather Coins

题意

给定一个 \(H\times W\) 的网格图,上面有 \(n\) 个格子有金币。

只能向右和向下走,求从 \((1,1)\) 走到 \((H,W)\) 最多能捡到多少金币,并给出一种路径。

思路

考虑对金币动态规划,每个金币 \((x,y)\) 只能从金币 \((p,q)(p\le x)(q \le y)\) 转移过来,转移方程:

\[dp_i = \max dp_j+1 \]

暴力转移时间复杂度 \(O(n^2)\),不能通过,而且存在后效性。

发现转移限制为二维偏序,可先把 \(x\) 从小到大排序,再用线段树维护所有 \(y\)。统计最小值及最小值的位置。

路径可记录一个 \(pre_i\) 表示 \(i\) 从哪里转移过来,倒着输出路径即可。

坑点:排序时不能只排 \(x\),当 \(x\) 相同时要按 \(y\) 从小到大排序。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
#define ll long long
const int N = 2e5 + 5;
int h, w, n;
struct P {int x, y;};
struct segt {
    struct node {
        int l, r, mx, MX;
    } t[N << 2];
    #define ls (p << 1)
    #define rs (p << 1 | 1)
    friend node operator + (node a, node b) {
        node res; res.l = a.l, res.r = b.r;
        if (a.mx > b.mx) res.mx = a.mx, res.MX = a.MX;
        else res.mx = b.mx, res.MX = b.MX;
        return res;
    }
    void build(int p, int l, int r) {
        t[p].l = l, t[p].r = r;
        if (l == r) return;
        int mid = (l + r) >> 1;
        build(ls, l, mid);
        build(rs, mid + 1, r);
    }
    void modify(int p, int id, int v, int val) {
        if (t[p].l == t[p].r) {
            t[p].mx = max(t[p].mx, v);
            if (t[p].mx == v) t[p].MX = val;
            return ;
        }
        if (id <= t[ls].r) modify(ls, id, v, val);
        else modify(rs, id, v, val);
        t[p] = t[ls] + t[rs];   
    }
    node query(int p, int l, int r) {
        if (l <= t[p].l && t[p].r <= r) return t[p];
        node res; res.l = -1;
        if (t[ls].r >= l) res = query(ls, l, r);
        if (t[rs].l <= r) {
            if (res.l == -1) res = query(rs, l, r);
            else res = res + query(rs, l, r);
        }
        return res;
    }
} T;
P a[N];
bool cmp(P A, P B) {
    if (A.x == B.x) return A.y < B.y;
    return A.x < B.x;
}
int dp[N], pre[N], ans, lst;
vector <int> path;
string ANS[N];
void solve() {
    cin >> h >> w >> n;
    for (int i = 1; i <= n; i ++) cin >> a[i].x >> a[i].y;
    a[0].x = 1, a[0].y = 1;
    a[n + 1].x = h, a[n + 1].y = w;
    sort(a + 1, a + n + 1, cmp);
    T.build(1, 1, max(h, w));
    T.modify(1, a[1].y, 1, 1);
    pre[1] = 0, dp[1] = 1, ans = 1, lst = 1;
    for (int i = 2; i <= n; i ++) {
        segt::node res = T.query(1, 1, a[i].y);
        dp[i] = dp[res.MX] + 1;
        pre[i] = res.MX;
        if (dp[i] > ans) {
            ans = dp[i];
            lst = i;
        }
        T.modify(1, a[i].y, dp[i], i);
    }
    pre[n + 1] = lst;
    int now = n + 1, tot = 0;
    while (now) {
        lst = pre[now], tot ++;
        for (int i = 1; i <= a[now].x - a[lst].x; i ++) ANS[tot] += 'D';
        for (int i = 1; i <= a[now].y - a[lst].y; i ++) ANS[tot] += 'R';
        now = pre[now];
    }
    cout << ans << "\n";
    for (int i = tot; i >= 1; i --) 
        cout << ANS[i];
    cout << "\n";
}
signed main() {
    int T = 1;
    // cin >> T;
    while (T --) 
        solve();
    return 0;
}

标签:Atcoder,return,Beginner,int,long,mx,369,id,dp
From: https://www.cnblogs.com/maniubi/p/18390995

相关文章

  • AtCoder Beginner Contest 369 补题记录(A~G)
    AconstintN=1000100;inta[N];signedmain(){intx,y;cin>>x>>y;if(x==y)cout<<"1\n";elseif(x%2==y%2)cout<<"3\n";elsecout<<"2\n";}BconstintN=1000100;inta[N];sign......
  • AtCoder Beginner Contest 369 A~D
    封面原图画师かにょこAtCoderBeginnerContest369我愿称之为等差数列场A-369题意给两个数,问能和他们构成等差数列的数有多少个代码#include<bits/stdc++.h>#definemod998244353usingnamespacestd;typedeflonglongll;typedefdoubledb;type......
  • ABC369
    Alink判断\(A\),\(B\)之间可不可以放一个数,如果可以就是\(3\)个,不行就是\(2\)个(左右),但是如果\(A\),\(B\)相等就只有一个。点击查看代码#include<bits/stdc++.h>usingnamespacestd;signedmain(){ inta,b; cin>>a>>b; intx=b-a; if(x!=0){ if(x%2==0......
  • Atcoder Beginner Contest 369
    AtcoderBeginnerContest369唯一的一发罚时吃在A题,消息了。A挂一发的原因是以为\(A,B\)都是一位数,然后循环范围开了\([-10,20]\)。#include<bits/stdc++.h>usingnamespacestd;intmain(){ ios::sync_with_stdio(false),cin.tie(nullptr);// int_;cin>>_;while......
  • AtCoder Beginner Contest 053
    A-ABC/ARC#include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;intmain(){ ios::sync_with_stdio(false),cin.tie(nullptr); intx; cin>>x; if(x<1200)cout<<"ABC"; elsecout<<"ARC&q......
  • luoguP5369 [PKUSC2018] 最大前缀和
    题目n<=20题解想了半天3位状态的折半,然后发现空间开不下(时间也不太行)所以放弃思考,直接枚举答案答案是a中的一个集合,设为S;记集合S的和为sum[S]考虑当S确定时,有多少种方案能使答案恰好为sum[S]。为了处理多种sum相同的情况,记S为从前往后考虑,第一次出现最大ans的集合;记剩余部......
  • Versal Prime 系列 VM2202 自适应 SoC平台,XCVM2202-1LSINSVH1369、XCVM2202-1MLINSVH1
    VersalPrime系列是一款高度集成、多核、异构计算平台,适用于数据中心网络、存储和有线通信等多种应用。它通过在优化了连接性的设备中实现低延迟的内联加速,为这些应用提供突破性的性能。VersalPrime系列VM2202自适应SoC相关型号:XCVM2202-1LSINSVH1369XCVM2202-2LSENSVH13......
  • Hitachi Vantara Programming Contest 2024(AtCoder Beginner Contest 368)F - Dividing
    https://atcoder.jp/contests/abc368/tasks/abc368_f#include<bits/stdc++.h>#definexfirst#defineysecondusingnamespacestd;typedeflonglongll;typedefpair<ll,char>pii;constintN=2e5+10,inf=1e9;lln,m,k;intb[N],sg[N],a[N];vector......
  • Atcoder [AGC006D] Median Pyramid Hard 题解 [ 紫 ] [ 二分 ] [ adhoc ]
    MedianPyramidHard:二分trick加上性质观察题。trick我们可以二分值域,然后把大于等于它的数标记成\(1\),其他标记为\(0\)(有些题需要标记成\(-1\)),然后根据这个来check方案是否可行,这通常通过判断某个数是否是\(1\)来实现。本质上其实就是check大于等于它的数能否成为......
  • AtCoder Beginner Contest 368
    A-Cut题意签到题思路代码#include<bits/stdc++.h>usingnamespacestd;voidsolve(){intn,k;scanf("%d%d",&n,&k);vector<int>v(n);for(inti=0;i<n;i++){scanf("%d",&v[i......