牛客周赛 Round 67

比赛链接

牛客周赛 Round 67

A题

代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> pii;
const int N = 3e5 + 5, M = 1e6 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;
int n;
string s;
void solve()
{
    cin >> n >> s;
    string str = "";
    for (char c : s)
    {
        if (c >= 'a' && c <= 'z')
            str.push_back(c);
    }
    for (char c : s)
    {
        if (c >= '0' && c <= '9')
            str.push_back(c);
    }
    for (char c : s)
    {
        if (c >= 'A' && c <= 'Z')
            str.push_back(c);
    }
    cout << str << endl;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int test = 1;
    // cin >> test;
    for (int i = 1; i <= test; i++)
    {
        solve();
    }
    return 0;
}

B题

思路

非常明显的二分,注意此题会爆longlong,所以我这里使用了python。

代码
n = int(input())
for i in range(n):
    a,b,c,d = map(int,input().split(' '))

    low = 0
    high = int(1e18)

    while low < high:
        mid = (low + high + 1) // 2;
        if mid * d < b * c:
            low = mid
        else:
            high = mid - 1

    print(a - low,end=' ')

print()

C题

思路

暴力枚举 A A A B B B的值即可。

代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int N = 3e5 + 5, M = 1e6 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;
int n, c, num, len;
string s1, s2, str;
string func(int x)
{
    if (x == 0) return "0";
    str = "";
    while (x)
    {
        char c = (x % 10) + '0';
        x /= 10;
        str.push_back(c);
    }
    reverse(str.begin(), str.end());
    return str;
}
bool check(int x)
{
    int y = c - x;
    s1 = func(x), s2 = func(y);
    return (int)(s1.size() + s2.size() + len + 2) == n;
}
void solve()
{
    cin >> n >> c;
    num = c;
    while (num)
    {
        len++;
        num /= 10;
    }
    int ans = 0;
    for (int i = 0; i <= c; i++)
    {
        if (check(i))
        {
            ans++;
        }
    }
    cout << ans << endl;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int test = 1;
    // cin >> test;
    for (int i = 1; i <= test; i++)
    {
        solve();
    }
    return 0;
}

D题

思路

0 0 0 n + 1 − k n+1-k n+1k不断循环填充即可。

代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int N = 3e5 + 5, M = 1e6 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;
int n, k;
void solve()
{
    cin >> n >> k;
    if (k > n)
    {
        cout << "NO" << endl;
    }
    else
    {
        cout << "YES" << endl;
        int op = n + 1 - k;
        for (int i = 1; i <= n; i++)
        {
            cout << (i % op) << " ";
        }
        cout << endl;
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int test = 1;
    // cin >> test;
    for (int i = 1; i <= test; i++)
    {
        solve();
    }
    return 0;
}

E题

思路

l o w = l 1 + l 2 low = l1+l2 low=l1+l2,令 h i g h = r 1 + r 2 high = r1+r2 high=r1+r2,答案就是 [ l o w , h i g h ] [low,high] [low,high]里数位和的最大值。假设当前 h i g h high high数位上的值 o p 1 op1 op1 l o w low low上的 o p 2 op2 op2大时,我们可以取 o p 1 − 1 op1-1 op11,后面全部取 9 9 9。我们通过不断枚举 h i g h high high的最高几位,不断贪心即可。

代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int N = 3e5 + 5, M = 1e6 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;
int l, r, L, R;
void solve()
{
    cin >> l >> r >> L >> R;
    int low = l + L, high = r + R;
    vector<int>a, b;
    while (low || high)
    {
        a.push_back(low % 10);
        b.push_back(high % 10);
        low /= 10, high /= 10;
    }
    reverse(a.begin(), a.end());
    reverse(b.begin(), b.end());
    int n = a.size();
    bool ok = false;
    int ans = 0, res = 0;
    for (int i = 0; i < n; i++)
    {
        if (a[i] < b[i])
        {
            ans = max({ans, res + b[i] - 1 + (n - i - 1) * 9, res + b[i]});
        }
        else
        {
            ans = max(ans, res + b[i]);
        }
        res += b[i];
    }
    cout << ans << endl;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int test = 1;
    cin >> test;
    for (int i = 1; i <= test; i++)
    {
        solve();
    }
    return 0;
}

F题

思路

我们计算每一个节点 u u u距离根节点的距离 d i s t u dist_{u} distu

根据每个节点的深度,按dfs序依次存到vector中。

使用线段树维护每一个深度中节点的 d i s t u dist_{u} distu的区间最大值。

最后,根据dfs序,二分查找即可。

代码
#include <bits/stdc++.h>

using namespace std;

#define int long long
#define double long double

typedef long long i64;
typedef unsigned long long u64;
typedef pair<int, int> pii;

const int N = 1e5 + 5, M = 1e6 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;

int n, q;
int depth[N], dist[N], L[N], R[N], cnt;
vector<pii>mp[N];
vector<int>dep[N];
struct segmenttree
{
    struct node
    {
        int l, r, maxx, tag;
    };
    vector<node>tree;

    segmenttree(): tree(1) {}
    segmenttree(int n): tree(n * 4 + 1) {}

    void pushup(int u)
    {
        auto &root = tree[u], &left = tree[u << 1], &right = tree[u << 1 | 1];
        root.maxx = max(left.maxx, right.maxx);
    }

    void pushdown(int u)
    {
        auto &root = tree[u], &left = tree[u << 1], &right = tree[u << 1 | 1];
        if (root.tag != 0)
        {
            left.tag += root.tag;
            right.tag += root.tag;
            left.maxx = left.maxx + root.tag;
            right.maxx = right.maxx + root.tag;
            root.tag = 0;
        }
    }

    void build(int u, int l, int r)
    {
        auto &root = tree[u];
        root = {l, r};
        if (l == r)
        {
            root.maxx = 0;
        }
        else
        {
            int mid = l + r >> 1;
            build(u << 1, l, mid);
            build(u << 1 | 1, mid + 1, r);
            pushup(u);
        }
    }

    void modify(int u, int l, int r, int val)
    {
        auto &root = tree[u];
        if (root.l >= l && root.r <= r)
        {
            root.maxx += val;
            root.tag += val;
            return;
        }
        pushdown(u);
        int mid = root.l + root.r >> 1;
        if (l <= mid) modify(u << 1, l, r, val);
        if (r > mid) modify(u << 1 | 1, l, r, val);
        pushup(u);
    }

    int query(int u, int l, int r)
    {
        auto &root = tree[u];
        if (root.l >= l && root.r <= r)
        {
            return root.maxx;
        }
        pushdown(u);
        int mid = root.l + root.r >> 1;
        int res = 0;
        if (l <= mid) res = query(u << 1, l, r);
        if (r > mid) res = max(res, query(u << 1 | 1, l, r));
        return res;
    }
};
vector<segmenttree>tree;
void dfs1(int u, int fu, int deep)
{
    L[u] = ++cnt;
    depth[u] = deep;
    dep[deep].push_back(u);
    for (auto[v, w] : mp[u])
    {
        if (v == fu) continue;
        dist[v] = dist[u] + w;
        dfs1(v, u, deep + 1);
    }
    R[u] = cnt;
}
void solve(int test_case)
{
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        dep[i].push_back(0);
    }
    for (int i = 1, a, b, w; i < n; i++)
    {
        cin >> a >> b >> w;
        mp[a].push_back({b, w});
        mp[b].push_back({a, w});
    }
    dfs1(1, -1, 1);
    for (int i = 1; i <= n; i++)
    {
        if (dep[i].size() > 1)
        {
            int len = dep[i].size();
            len--;
            segmenttree smt(len);
            smt.build(1, 1, len);
            for (int j = 1; j < dep[i].size(); j++)
            {
                smt.modify(1, j, j, dist[dep[i][j]]);
            }
            tree.push_back(smt);
        }
    }
    cin >> q;
    for (int i = 1, u, d; i <= q; i++)
    {
        cin >> u >> d;
        int deep = depth[u] + d;
        if (deep > n)
        {
            cout << -1 << endl;
            continue;
        }
        if (dep[deep].size() < 2)
        {
            cout << -1 << endl;
            continue;
        }
        int idx = deep - 1;
        int l = 1, r = dep[deep].size() - 1;
        int ansl = -1, ansr = -1;
        while (l < r)
        {
            int mid = l + r >> 1;
            if (L[dep[deep][mid]] >= L[u])
            {
                r = mid;
                ansl = mid;
            }
            else l = mid + 1;
        }
        if (L[dep[deep][l]] >= L[u])
        {
            ansl = l;
        }
        if (ansl == -1)
        {
            cout << -1 << endl;
            continue;
        }
        int low = 1, high = dep[deep].size() - 1;
        while (low < high)
        {
            int mid = low + high + 1 >> 1;
            if (L[dep[deep][mid]] <= R[u])
            {
                ansr = mid;
                low = mid;
            }
            else high = mid - 1;
        }
        if (L[dep[deep][low]] <= R[u])
        {
            ansr = low;
        }
        if (ansr == -1)
        {
            cout << -1 << endl;
            continue;
        }
        if (ansl > ansr)
        {
            cout << -1 << endl;
        }
        else
        {
            cout << tree[idx].query(1, ansl, ansr) - dist[u] << endl;
        }
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int test = 1;
    // cin >> test;
    for (int i = 1; i <= test; i++)
    {
        solve(i);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值