The 4th Universal Cup. Stage 8: Grand Prix of Poland

Preface

不知道 VP 什么还是选了这赛季的外国场 UCUP,毕竟还是正规区域赛题目质量还是有保障的

就是整体难度相对偏低,签到和前期题比较多,同时算法题相对较少,不过这些问题也是老生常谈了


A. AIMPPZ

签到,枚举有几个 AI 即可

#include<cstdio>
#include<iostream>
using namespace std;
int n;
int main()
{
    scanf("%d",&n);
    int fact_5=0,tmp=n;
    while (tmp%5==0) ++fact_5,tmp/=5;
    int ans=n,times=0; tmp=1;
    for (int i=1;i<=fact_5;++i)
    {
        tmp*=5;
        if (2*i>n/tmp) continue;
        if (n/tmp<ans) ans=n/tmp,times=i;
    }
    for (int i=1;i<=times;++i)
    printf("AI");
    for (int i=1;i<=ans-2*times;++i)
    printf("B");
    return 0;
}

B. Beats

考虑枚举一段前缀,钦定除了这段前缀外的后缀全部用第二种操作,此时只要求出需要多少次第一种操作能给前缀排序

手玩一下会发现拿个队列维护一下可以不动的元素即可

#include<bits/stdc++.h>
using namespace std;

const int N = 2e5+5;
int n, A[N];
int que[N], fr=0, ed=-1;
signed main() {
    ios::sync_with_stdio(0); cin.tie(0);
    cin >> n;
    int ans = n;
    for (int i=1; i<=n; ++i) cin >> A[i];
    for (int i=1; i<=n; ++i) {
        if (ed<fr || A[i]>que[ed]) que[++ed]=A[i];
        else {
            while (fr<=ed && A[i]>que[fr]) ++fr;
        }
        ans = min(ans, n-(ed-fr+1));
    }
    cout << ans << '\n';
    return 0;
}

C. Count Triangular Sequences

直接对 \(\{a_i\}\) 计数比较困难,我们考虑对其差分数组进行计数

\(d_i=a_i-(a_{i-1}+a_{i-2})\),特别地,\(d_1=a_1,d_2=a_2-a_1\)

手玩一会我们会发现对于 \(i\ge 3\),满足 \(a_i=\sum_{j=1}^n fib_j\times d_{i+1-j}\),其中 \(fib\) 是以 \(1\) 开头的斐波那契数列

因此这个题本质上就变成一个类似于背包的问题,不难发现由于 \(a_i\le 200000\),因此序列长度 \(\le 28\),用一个类似于完全背包的东西计数即可

注意要特判序列开头两个元素相同的情形

#include<cstdio>
#include<iostream>
#include<cstring>
#define RI register int
#define CI const int&
using namespace std;
const int N=200005,mod=1e9+7,inv2=(mod+1)/2;
int n,fib[30],fact[30],f[30][N];
inline void inc(int& x,CI y)
{
    if ((x+=y)>=mod) x-=mod;
}
inline void dec(int& x,CI y)
{
    if ((x-=y)<0) x+=mod;
}
int main()
{
    scanf("%d",&n);
    int pw=n,ans=0; fact[0]=1;
    for (RI i=1;i<=n;++i,pw=1LL*pw*n%mod) inc(ans,pw);
    int m; fib[0]=0; fib[1]=1;
    for (RI i=2;;++i)
    {
        fib[i]=fib[i-1]+fib[i-2];
        if (fib[i]>n) { m=i; break; }
    }
    for (RI i=1;i<=m;++i) fact[i]=1LL*fact[i-1]*i%mod;
    // printf("m = %d\n",m);
    f[1][0]=1;
    for (RI i=1;i<=min(n,m);++i)
    for (RI j=0;j<=n;++j)
    {
        if (f[i][j]==0) continue;
        inc(f[i+1][j],f[i][j]);
        if (j+fib[i]<=n)
        {
            inc(f[i][j+fib[i]],f[i][j]);
            if (j+fib[i]+fib[i-1]<=n)
            {
                dec(ans,1LL*fact[i]*f[i][j]%mod);
            } else
            {
                dec(ans,1LL*fact[i]*f[i][j]%mod*inv2%mod);
            }
        }
    }
    return printf("%d\n",ans),0;
}

E. Enigma

经典势能分析题,考虑直接暴力跑多源最短路,每次增加一个新起点时,当且仅当它能减小其它点的答案时才松弛入队

因为第一次操作后每个点的答案 \(\le 25\),而一个点入队会导致其答案至少减少 \(1\),因此总的入队次数就是 \(25\times 100000\) 级别的

#include<cstdio>
#include<iostream>
#include<vector>
#include<queue>
#define RI register int
#define CI const int&
using namespace std;
const int N=100000;
int n,dis[N+5],bkt[N+5]; vector <int> v[N+5];
int main()
{
    for (RI mask=0;mask<N;++mask)
    {
        for (RI i=1,base=1;i<=5;++i,base*=10)
        {
            int d=mask/base%10;
            if (d+1<=9) v[mask].push_back(mask+base);
            else v[mask].push_back(mask-base*9); // d == 9
            if (d-1>=0) v[mask].push_back(mask-base);
            else v[mask].push_back(mask+base*9); // d == 0
        }
        dis[mask]=N; ++bkt[dis[mask]];
    }
    // for (auto x:v[0]) printf("%d ",x); putchar('\n');
    for (scanf("%d",&n);n;--n)
    {
        char s[10]; scanf("%s",s);
        int mask=0;
        for (RI i=0;i<5;++i)
        mask=mask*10+(s[i]-'0');
        queue <int> q; q.push(mask);
        auto upt=[&](int& x,CI y)
        {
            --bkt[x]; x=y; ++bkt[x];
        };
        upt(dis[mask],0);
        while (!q.empty())
        {
            int now=q.front(); q.pop();
            // printf("mask = %d\n",now);
            for (auto to:v[now])
            {
                // printf("to = %d\n",to);
                if (dis[to]>dis[now]+1)
                {
                    upt(dis[to],dis[now]+1);
                    q.push(to);
                }
            }
        }
        for (RI i=25;i>=0;--i)
        if (bkt[i]!=0)
        {
            printf("%d %d\n",i,bkt[i]);
            break;
        }
    }
    return 0;
}

F. Finances

这题纯队友讨论+写出来的,我题目都没看

#include <bits/stdc++.h>

using llsi = long long signed int;

#define int llsi

constexpr int $n = 1'000'006;

int n, m;
int a[$n];
std::vector<std::tuple<int, llsi, int>> e[$n];
std::vector<std::pair<int, llsi>> e2[$n];
int ecc[$n], ecc_cnt;
llsi ecc_a[$n];

int __edge_cnt = 0;

void add_edge(int u, int v, llsi c) {
    e[u].emplace_back(v, c, __edge_cnt++);
    e[v].emplace_back(u, c, __edge_cnt++);
}

namespace Tarjan {
    int low[$n], dfn[$n];
    std::stack<int> st;
    std::vector<std::tuple<int, int, llsi>> bdg;
    int cnt;

    void tarjan(int x, std::tuple<int, llsi, int> be) {
        auto [fa, c, las_id] = be;
        low[x] = dfn[x] = ++cnt;
        st.push(x);
        for(auto [out, cc, id]: e[x]) {
            if(id == las_id) continue;
            if(!dfn[out]) {
                tarjan(out, {x, cc, id ^ 1});
                low[x] = std::min(low[x], low[out]);
            } else {
                low[x] = std::min(low[x], dfn[out]);
            }
        }
        if(dfn[x] == low[x]) {
            ecc[x] = ++ecc_cnt;
            ecc_a[ecc_cnt] += a[x];
            while(st.top() != x) {
                ecc[st.top()] = ecc_cnt;
                ecc_a[ecc_cnt] += a[st.top()];
                st.pop();
            }
            st.pop();
            if(fa != -1) bdg.emplace_back(x, fa, c);
        }
    }
}


void init() {
    __edge_cnt = 0;
    Tarjan::cnt = 0;
    Tarjan::bdg.clear();
    ecc_cnt = 0;
    for(int i = 0; i <= n; ++i) {
        e[i].clear();
        e2[i].clear();
        Tarjan::low[i] = 0;
        Tarjan::dfn[i] = 0;
        ecc_a[i] = 0;
    }
}

std::pair<bool, llsi> dfs(int cur, int fa, llsi c) {
    // std::cerr << std::format("dfs({} {} {})", cur, fa, c) << char(10);
    llsi sum = ecc_a[cur];
    
    for(auto [out, cc]: e2[cur]) if(out != fa) {
        auto [res_out, sum_out] = dfs(out, cur, cc);
        if(!res_out) return { false, 0 };
        sum += sum_out;
    }

    return { std::abs(sum) <= c, sum };
}

bool work() {
    std::cin >> n >> m;
    init();
    for(int i = 1; i <= n; ++i) std::cin >> a[i];
    for(int i = 1, u, v; i <= m; ++i) {
        llsi c;
        std::cin >> u >> v >> c;
        add_edge(u, v, c);
    }

    Tarjan::tarjan(1, {-1, -1, -1});
    // for(int i = 1; i <= n; ++i) std::cerr << ecc[i] << char(i == n ? 10 : 32);
    for(auto [u, v, c]: Tarjan::bdg) {
        e2[ecc[u]].emplace_back(ecc[v], c);
        e2[ecc[v]].emplace_back(ecc[u], c);
    }

    return dfs(1, 0, 0).first;
}

int32_t main() {
    std::ios::sync_with_stdio(false);
    int T; std::cin >> T; while(T--) std::cout << (work() ? "TAK\n" : "NIE\n");
    return 0;
}

H. Hacking

签到,我题都没看

#include <bits/stdc++.h>

int main() {
    int n; std::cin >> n;
    int sum = 0;
    while(n--) { int a; std::cin >> a; sum += a; }
    std::cout << 600 - sum << char(10);
    return 0;
}

I. ICPC Isolation

爆搜+打表,真是公公又式式

#include <bits/stdc++.h>

const char* UNAME[27] = { "UW", "UJ", "UWR", "MAP", "PW", "AGH", "PG", "NLU", "PUT", "PO", "PWR", "SGGW", "UMCS", "UR", "ZUT", "DTP", "GOO", "HUA", "KUL", "PL", "PM", "PS", "UAM", "UG", "UMK", "UO", "WAT" };
int        UCOUNT[27] = {  11 ,   9 ,    8 ,    7 ,   6 ,    5 ,   4 ,    3 ,    3 ,   2 ,    2 ,     2 ,     2 ,   2 ,    2 ,    1 ,    1 ,    1 ,    1 ,   1 ,   1 ,   1 ,    1 ,   1 ,    1 ,   1 ,    1  };

extern int ans[27][8][10];

void print_table(const std::string &prefix, int ans[8][10]) {
    std::cout << "    // " << prefix << char(10);
    for(int i = 0; i < 8; ++i) {
        std::cout << "    ";
        for(int j = 0; j < 10; ++j)
            std::cout << std::setw(2) << ans[i][j] << ",",
            std::cout << char(j == 9 ? 10 : 32);
    }
}

void print_ans() {
    std::cout << "int ans[27][8][10] = {\n";
    for(int k = 0; k < 27; ++k)
        print_table(std::format("ars = {} ({})", k, UNAME[k]), ans[k]);
    std::cout << "};\n";
    return ;
}

bool dfs(int ans[8][10], int i, int j) {
    if(i == 8) return true;
    // std::cerr << "[dfs] i, j = " << i << ", " << j << char(10);

    int ni = i, nj = j + 1;
    if(nj == 10) nj = 0, ni += 1;
    
    for(int cl = 0; cl < 27; ++cl) if(UCOUNT[cl]) {
        bool res = false;;
        for(auto [si, sj]: (int[4][2]){{i - 1, j - 1}, {i - 1, j}, {i - 1, j + 1}, {i, j - 1}}) {
            if(si < 0 || si >= 8) continue;
            if(sj < 0 || sj >= 10) continue;
            if(cl == ans[si][sj]) goto __continue__;
        }
        UCOUNT[cl]--; ans[i][j] = cl;
        res = dfs(ans, ni, nj);
        UCOUNT[cl]++;
        if(res) return true;
__continue__: continue;
    }

    return false;
}

void prep_ans() {
    for(int ars = 0; ars < 27; ++ars) {
        std::cerr << "Calculate ans for (ars = " << ars << ")" << std::endl;
        ans[ars][0][0] = ars;
        UCOUNT[ars]--;
        dfs(ans[ars], 0, 1);
        UCOUNT[ars]++;
    }
}

int main() {
    std::ios::sync_with_stdio(false);

    // memset(ans, -1, sizeof(ans));
    // prep_ans();
    // print_ans();
    // return 0;

    std::string ars; std::cin >> ars;

    int k;
    for(k = 0; k < 27; ++k) if(ars == UNAME[k]) break;
    assert(k < 27);

    for(int i = 0; i < 8; ++i) for(int j = 0; j < 10; ++j)
        std::cout << UNAME[ans[k][i][j]] << char(j == 9 ? 10 : 32);

    return 0;
}

int ans[27][8][10] = {
    // ars = 0 (UW)
     0,  1,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  2,  3,  2,  3,
     0,  1,  0,  1,  0,  1,  0,  1,  0,  4,
     2,  3,  2,  3,  2,  4,  5,  4,  5,  6,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  4,
     5,  6,  7,  8,  9,  8,  9,  8, 10, 11,
    10, 11, 12, 13, 12, 13, 14, 15, 14, 16,
    17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
    // ars = 1 (UJ)
     1,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     2,  3,  2,  3,  2,  3,  2,  3,  2,  3,
     0,  1,  0,  1,  0,  1,  0,  1,  0,  4,
     2,  3,  2,  3,  2,  4,  5,  4,  5,  6,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  4,
     5,  6,  7,  8,  9,  8,  9,  8, 10, 11,
    10, 11, 12, 13, 12, 13, 14, 15, 14, 16,
    17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
    // ars = 2 (UWR)
     2,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  3,  2,  3,  2,  3,  2,  3,  2,  3,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  4,  5,  4,  5,  4,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  7,  8,  9,  8,  9,  8, 10, 11,
    10, 11, 12, 13, 12, 13, 14, 15, 14, 16,
    17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
    // ars = 3 (MAP)
     3,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  4,  5,  4,  5,  4,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  7,  8,  9,  8,  9,  8, 10, 11,
    10, 11, 12, 13, 12, 13, 14, 15, 14, 16,
    17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
    // ars = 4 (PW)
     4,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  7,  8,  9,  8,  9,  8, 10, 11,
    10, 11, 12, 13, 12, 13, 14, 15, 14, 16,
    17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
    // ars = 5 (AGH)
     5,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     6,  7,  8,  9,  8,  4,  8,  9, 10, 11,
    10, 11, 12, 13, 12, 13, 14, 15, 14, 16,
    17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
    // ars = 6 (PG)
     6,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  7,  8,  9,  8,  4,  8,  9, 10, 11,
    10, 11, 12, 13, 12, 13, 14, 15, 14, 16,
    17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
    // ars = 7 (NLU)
     7,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  8,  9,  8,  4,  8,  9, 10, 11,
    10, 11, 12, 13, 12, 13, 14, 15, 14, 16,
    17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
    // ars = 8 (PUT)
     8,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  7,  8,  9,  4,  8,  9, 10, 11,
    10, 11, 12, 13, 12, 13, 14, 15, 14, 16,
    17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
    // ars = 9 (PO)
     9,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  7,  8,  9,  4,  8, 10,  8, 10,
    11, 12, 11, 12, 13, 14, 13, 14, 15, 16,
    17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
    // ars = 10 (PWR)
    10,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  7,  8,  9,  4,  8,  9,  8, 10,
    11, 12, 11, 12, 13, 14, 13, 14, 15, 16,
    17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
    // ars = 11 (SGGW)
    11,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  7,  8,  9,  4,  8,  9,  8, 10,
    10, 11, 12, 13, 12, 13, 14, 15, 14, 16,
    17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
    // ars = 12 (UMCS)
    12,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  7,  8,  9,  4,  8,  9,  8, 10,
    10, 11, 12, 11, 13, 14, 13, 14, 15, 16,
    17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
    // ars = 13 (UR)
    13,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  7,  8,  9,  4,  8,  9,  8, 10,
    10, 11, 12, 11, 12, 13, 14, 15, 14, 16,
    17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
    // ars = 14 (ZUT)
    14,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  7,  8,  9,  4,  8,  9,  8, 10,
    10, 11, 12, 11, 12, 13, 14, 13, 15, 16,
    17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
    // ars = 15 (DTP)
    15,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  7,  8,  9,  4,  8,  9,  8, 10,
    10, 11, 12, 11, 12, 13, 14, 13, 14, 16,
    17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
    // ars = 16 (GOO)
    16,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  7,  8,  9,  4,  8,  9,  8, 10,
    10, 11, 12, 11, 12, 13, 14, 13, 14, 15,
    17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
    // ars = 17 (HUA)
    17,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  7,  8,  9,  4,  8,  9,  8, 10,
    10, 11, 12, 11, 12, 13, 14, 13, 14, 15,
    16, 18, 19, 20, 21, 22, 23, 24, 25, 26,
    // ars = 18 (KUL)
    18,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  7,  8,  9,  4,  8,  9,  8, 10,
    10, 11, 12, 11, 12, 13, 14, 13, 14, 15,
    16, 17, 19, 20, 21, 22, 23, 24, 25, 26,
    // ars = 19 (PL)
    19,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  7,  8,  9,  4,  8,  9,  8, 10,
    10, 11, 12, 11, 12, 13, 14, 13, 14, 15,
    16, 17, 18, 20, 21, 22, 23, 24, 25, 26,
    // ars = 20 (PM)
    20,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  7,  8,  9,  4,  8,  9,  8, 10,
    10, 11, 12, 11, 12, 13, 14, 13, 14, 15,
    16, 17, 18, 19, 21, 22, 23, 24, 25, 26,
    // ars = 21 (PS)
    21,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  7,  8,  9,  4,  8,  9,  8, 10,
    10, 11, 12, 11, 12, 13, 14, 13, 14, 15,
    16, 17, 18, 19, 20, 22, 23, 24, 25, 26,
    // ars = 22 (UAM)
    22,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  7,  8,  9,  4,  8,  9,  8, 10,
    10, 11, 12, 11, 12, 13, 14, 13, 14, 15,
    16, 17, 18, 19, 20, 21, 23, 24, 25, 26,
    // ars = 23 (UG)
    23,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  7,  8,  9,  4,  8,  9,  8, 10,
    10, 11, 12, 11, 12, 13, 14, 13, 14, 15,
    16, 17, 18, 19, 20, 21, 22, 24, 25, 26,
    // ars = 24 (UMK)
    24,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  7,  8,  9,  4,  8,  9,  8, 10,
    10, 11, 12, 11, 12, 13, 14, 13, 14, 15,
    16, 17, 18, 19, 20, 21, 22, 23, 25, 26,
    // ars = 25 (UO)
    25,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  7,  8,  9,  4,  8,  9,  8, 10,
    10, 11, 12, 11, 12, 13, 14, 13, 14, 15,
    16, 17, 18, 19, 20, 21, 22, 23, 24, 26,
    // ars = 26 (WAT)
    26,  0,  1,  0,  1,  0,  1,  0,  1,  0,
     1,  2,  3,  2,  3,  2,  3,  2,  3,  2,
     0,  4,  0,  1,  0,  1,  0,  1,  0,  1,
     2,  3,  2,  3,  2,  3,  4,  5,  4,  5,
     0,  4,  5,  4,  5,  6,  7,  6,  7,  6,
     5,  6,  7,  8,  9,  4,  8,  9,  8, 10,
    10, 11, 12, 11, 12, 13, 14, 13, 14, 15,
    16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
};

J. Jury of AMPPZ

考虑二分答案 \(x\),则贪心地让计算几何题里 \((val,id)\) 二元组最大的那 \(x\) 个进入前 \(k\) 名一定最优

要最大化它们的最小值,只需要从小到大排序后依次加上 \(n,n-1,\ldots,n-x+1\) 即可

对于非计算几何题,前 \(k-x\) 大的元素其实可以忽略不管,我们只要保证上面的最小值能超过剩下题的最大值即可

还是如法炮制地贪心,从大到小排序后依次加上 \(1,2,\ldots\) 即可,最后求个最大值和前面比较一下

#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#define RI register int
#define CI const int&
using namespace std;
int n,k; vector <pair <int,int>> A,B;
int main()
{
    scanf("%d%d",&n,&k);
    for (RI i=1;i<=n;++i)
    {
        int x,a,b,c,d;
        scanf("%d%d%d%d%d",&x,&a,&b,&c,&d);
        if (x==1) A.push_back({a+b+c+d,-i});
        else B.push_back({a+b+c+d,-i});
    }
    sort(A.begin(),A.end(),greater <pair <int,int>>());
    sort(B.begin(),B.end(),greater <pair <int,int>>());
    int l=1,r=min(k,(int)A.size()),mid,res=0;
    auto check=[&](CI x)
    {
        pair <int,int> mn={1e9,0};
        for (RI i=0;i<x;++i)
        mn=min(mn,{A[i].first+n-x+1+i,A[i].second});
        for (RI i=k-x;i<(int)B.size();++i)
        if (mn<make_pair(B[i].first+i-(k-x)+1,B[i].second)) return false;
        return true;
    };
    while (l<=r)
    if (check(mid=l+r>>1)) res=mid,l=mid+1; else r=mid-1;
    return printf("%d\n",res),0;
}


K. Kids' Blocks

又是个我没看题的签到

#include <bits/stdc++.h>

constexpr int $n = 300'005;
int a[$n], pm[$n], sm[$n];

int main() {
    std::ios::sync_with_stdio(false);
    int n; std::cin >> n;
    for(int i = 1; i <= n; ++i) std::cin >> a[i];
    pm[1] = a[1]; for(int i =     2; i <= n; ++i) pm[i] = std::max(pm[i - 1], a[i]);
    sm[n] = a[n]; for(int i = n - 1; i >= 1; --i) sm[i] = std::max(sm[i + 1], a[i]);
    int ans = 0x7fff'ffff;
    for(int i = 1; i < n; ++i) ans = std::min(ans, std::abs(sm[i + 1] - pm[i]));
    std::cout << ans << char(10);
    return 0;
}

L. Linear Averaging

我去蹲了个坑队友就会这个题了,好像是个转化成几何问题后用 convex trick 搞一搞的题,只能说队友太有实力

#include <bits/stdc++.h>

using llsi = long long signed int;
using ldb = long double;

#define double ldb

constexpr int $n = 500005;

int n, m, k;
int a[$n];
llsi sum_k[$n];
llsi pos[$n], neg[$n], ans[$n];

double ans1[$n], ans2[$n];
void solve(double ans[$n]) {
    std::vector<std::pair<double, double>> lines;

    for(llsi i = 1; i <= m; ++i) {
        if(pos[i] >= 0) {
            double K = double(pos[i]);
            double B = double(i);
            if(K == 0) {
                ans[i] = 0.0L;
                continue;
            }
            while(lines.size() && K >= lines.back().first) lines.pop_back();
            while(lines.size() >= 2) {
                auto [K1, B1] = lines[lines.size() - 1];
                auto [K2, B2] = lines[lines.size() - 2];
                auto Y1 = (K1 * B2 - K2 * B1) / (K1 - K2);
                auto Y2 = (K1 * B  - K  * B1) / (K1 - K );
                if(Y2 <= Y1) break;
                lines.pop_back(); 
            }
            lines.emplace_back(K, B);
        }

        while(lines.size() >= 2) {
            auto [K1, B1] = lines[lines.size() - 1];
            auto [K2, B2] = lines[lines.size() - 2];
            if((K1 * B2 - K2 * B1) / (K1 - K2) >= i) break;
            lines.pop_back();
        }

        // std::cerr << "[DEBUG solve() i = " << i << "] lines:";
        // if(lines.empty()) std::cerr << " [empty]";
        // else for(auto [K, B]: lines) std::cerr << " (" << K << ", " << B << ")";
        // std::cerr << char(10);

        if(lines.size()) {
            auto [K, B] = lines.back();
            ans[i] = ((double)i - B) / (K / k);
        } else {
            ans[i] = 1e16;
        }
        // std::cerr << "ans[" << i << "] = " << ans[i] << char(10);
    }
}

const char* clip(llsi a, llsi INF) {
    if(a >= INF) return "INF";
    if(a <= -INF) return "NNF";
    static char ss[40];
    std::sprintf(ss, "%lld", a);
    return ss;
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cerr << std::fixed << std::setprecision(2);
    std::cin >> n >> m >> k;
    
    for(int i = 1; i <= n; ++i) std::cin >> a[i];
    /* prep sum_k */ {
        llsi s = 0;
        for(int i = 1; i < k; ++i) s += a[i];
        for(int i = k; i <= n; ++i) {
            s += a[i];
            sum_k[i - k + 1] = s;
            s -= a[i - k + 1];
        }
    }

    std::deque<int> q_pos, q_neg;
    for(int i = 1; i <= m; ++i)
        pos[i] = -4e18,
        neg[i] = 4e18;
    for(int i = 1; i <= n; ++i)
        pos[a[i]] = llsi(k) * llsi(a[i]),
        neg[a[i]] = llsi(k) * llsi(a[i]);
    for(int i = 1; i <= n; ++i) {
        if(i + k - 1 <= n) {
            while(q_pos.size() && sum_k[i] >= sum_k[q_pos.back()]) q_pos.pop_back();
            while(q_neg.size() && sum_k[i] <= sum_k[q_neg.back()]) q_neg.pop_back();
            q_pos.push_back(i);
            q_neg.push_back(i);
        }
        while(q_pos.size() && q_pos.front() + k - 1 < i) q_pos.pop_front();
        while(q_neg.size() && q_neg.front() + k - 1 < i) q_neg.pop_front();
        pos[a[i]] = std::max(pos[a[i]], sum_k[q_pos.front()]);
        neg[a[i]] = std::min(neg[a[i]], sum_k[q_neg.front()]);
    }

    for(llsi i = 1; i <= m; ++i)
        pos[i] -= i * k,
        neg[i] -= i * k; 

    solve(ans1);
    for(int i = 1; i <= m; ++i) pos[i] = -neg[m - i + 1];
    solve(ans2);

    // std::cerr << "[DEBUG] pos[]: "; for(int i = 1; i <= m; ++i) std::cerr << clip(pos[i], 100000) << char(i == m ? 10 : 32);
    // std::cerr << "[DEBUG] neg[]: "; for(int i = 1; i <= m; ++i) std::cerr << clip(neg[i], 100000) << char(i == m ? 10 : 32);
    // std::cerr << "[DEBUG] ans1[]: "; for(int i = 1; i <= m; ++i) std::cerr << ans1[i] << char(i == m ? 10 : 32);
    // std::cerr << "[DEBUG] ans2[]: "; for(int i = 1; i <= m; ++i) std::cerr << ans2[i] << char(i == m ? 10 : 32);
    
    std::cout << std::fixed << std::setprecision(20);
    for(int i = 1; i <= m; ++i) {
        double ans = std::min(ans1[i], ans2[m - i + 1]);
        if(ans < 0.0L || ans > 1.0L) std::cout << "-1\n";
        else std::cout << ans << char(10);
    }

    return 0;
}

Postscript

感觉两天一训强度还是挺大的,不禁让我想起之前每天一训是怎么坚持下来的

posted @ 2026-01-23 14:56  空気力学の詩  阅读(0)  评论(0)    收藏  举报