“21 天好习惯”第一期-8

A String Game

题意

给一个长度为 n n n 的字符串 s s s,输出将 s s s x x x 个字符移植末尾的结果。

Solution

按题意模拟。( x x x 数量级较大,对 n n n 取模后缩小实际有效操作次数即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, j, k) for (ll(i) = (j); (i) <= (k); (++i))
void solve() {
    ll n, x;
    string s;
    cin >> n >> x >> s;
    x %= n;
    rep(i, x, n - 1) cout << s[i];
    rep(i, 0, x - 1) cout << s[i];
    cout << endl;
}
signed main() {
    solve();
    return 0;
}

B Sequence Game

题意

给定长度为 n n n 的数组 a a a,数组中每个数有 k k k 个可能取值,求数组 a a a 的最长上升子序列

Solution

题中保证给定的 k k k 个可能取值单调,且取值大小均小于1000,则考虑采用一个dp数组记录 d p [ i ] dp[i] dp[i] 表示以 i i i 数字结尾的最长上升子序列长度即可。

#include <bits/stdc++.h>
using namespace std;
#define rep(i, j, k) for (ll(i) = (j); (i) <= (k); (++i))
#define mem(x, y) memset(x, y, sizeof(x))
typedef long long ll;
const int N = 1e6 + 7;
int n, k, ans, tmp[N], dp[N];
signed main() {
    cin >> k >> n;
    rep(i, 1, n) {
        int mx = 0, now = 0, x;
        mem(tmp, 0);
        rep(j, 1, k) {
            cin >> x;
            while (now < x)
                mx = max(mx, dp[now]), now++;
            tmp[x] = mx + 1;
        }
        rep(j, 0, 1000) dp[j] = max(tmp[j], dp[j]), ans = max(ans, dp[j]);
    }
    cout << ans;
    return 0;
}

C Simple Game

题意

一张具有 n n n 个结点的有向图中,问每个节点能够到达的结点最小编号,输出排序去重后的结果。

Solution

一开始没仔细想,直接建图跑dfs,然后更新访问结点,结果发现如果简单判环走到走过的地方就不走的时候,结点的更新不及时导致环路上其他结点同样不能及时更新,95分代码,其实数据强一点不可能会这么高得分的

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, j, k) for (ll(i) = (j); (i) <= (k); (++i))
const int N = 1e5 + 7;
vector<ll> to[N];
ll ans[N];
bool vis[N];
ll dfs(int p) {
    if (vis[p])
        return ans[p];
    vis[p] = 1;
    for (auto i : to[p])
        ans[p] = min(ans[p], dfs(i));
    return ans[p];
}
signed main() {
    ll n, m, u, v;
    cin >> n >> m;
    rep(i, 1, n) ans[i] = i;
    rep(i, 1, m) cin >> u >> v, to[u].emplace_back(v);
    rep(i, 1, n) dfs(i);
    vector<ll> a;
    rep(i, 1, n) a.emplace_back(ans[i]);
    sort(a.begin(), a.end()), a.erase(unique(a.begin(), a.end()), a.end());
    for (auto i : a)
        cout << i << ' ';
    return 0;
}

正解应该建反图,然后直接跑dfs即可,从小到大第一次访问到的即为当前结点能到达的最小值。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, j, k) for (ll(i) = (j); (i) <= (k); (++i))
const int N = 1e5 + 7;
vector<ll> to[N];
int ans[N];
bool vis[N];
void dfs(int fa, int p) {
    ans[p] = min(ans[p], fa);
    if (vis[p])
        return;
    vis[p] = 1;
    for (auto i : to[p])
        dfs(ans[p], i);
}
signed main() {
    int n, m, u, v;
    cin >> n >> m;
    rep(i, 1, n) ans[i] = i;
    rep(i, 1, m) cin >> u >> v, to[v].emplace_back(u);
    rep(i, 1, n) dfs(i, i);
    vector<ll> a;
    rep(i, 1, n) a.emplace_back(ans[i]);
    sort(a.begin(), a.end()), a.erase(unique(a.begin(), a.end()), a.end());
    for (auto i : a)
        cout << i << ' ';
    return 0;
}

D Sweet Game

题意

一共有 n n n 个糖果,每个糖果的甜度会随着时间变化。

每隔一个单位时间吃掉一个糖果,当吃掉编号为 i i i 的糖果时,需保证在吃这个糖果前编号比 i i i 大的糖果均被吃完;或者如果编号比 i i i 大的糖果没有吃完,则接下来必须将编号比 i i i 大的糖果吃完,即此时不能吃编号比 i i i 小的糖果。

Solution

构造一个糖果序列,考虑该以该序列作为吃糖顺序。

根据题目要求,要保证编号为 i i i 的糖果被吃掉之前或之后吃这个糖果前编号比 i i i 大的糖果均被吃完的情况,应依次从后往前考虑吃糖顺序。

当吃掉编号为 n n n​​ 的糖时,接下来可以考虑是在吃编号为 n n n​​ 的糖之前或之后吃编号为 n − 1 n-1 n1​​ 的糖, n − 2 n-2 n2​​ 同理,依此类推。于是假定当前已经确定编号大于 x + 1 x+1 x+1​​ 的糖之后的吃糖顺序,接下考虑编号为 x x x​​ 的糖在什么时候吃,此时有两种选择,在最开始的时候吃这颗糖,对答案的贡献为 a [ x ] + s u m [ x + 1 ] a[x]+sum[x+1] a[x]+sum[x+1]​​ ,其中 s u m [ x + 1 ] sum[x+1] sum[x+1]​​ 表示一个单位时间内编号大于 x x x​​ 的糖甜度的变化之和;或者编号大于 x + 1 x+1 x+1​​ 的糖全部吃完后吃这颗糖,对答案的贡献为 a [ x ] + d [ x ] ∗ ( n − x ) a[x]+d[x]*(n-x) a[x]+d[x](nx)​​ ,其中 d [ x ] d[x] d[x]​​ 表示单位时间内编号为 x x x​​ 的糖甜度的变化值, n − x n-x nx​ 表示这个糖在过了多久被吃掉。

#include <bits/stdc++.h>
using namespace std;
#define int ll
#define rep(i, j, k) for (ll(i) = (j); (i) <= (k); (++i))
#define rrep(i, j, k) for (ll i = (ll)(j); i >= (ll)(k); i--)
typedef long long ll;
const int N = 1e5 + 7;
ll a[N], d[N], sum[N], n, l, r;
signed main() {
    cin >> n;
    rep(i, 1, n) cin >> a[i];
    rep(i, 1, n) cin >> d[i];
    rrep(i, n, 1) sum[i] = d[i] + sum[i + 1];
    ll ans = a[n];
    rrep(i, n - 1, 1) ans += a[i] + max(sum[i + 1], d[i] * (n - i));
    cout << ans << '\n';
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值