Solutions - NOISG 2022 Finals 重现赛

为什么我每次都要在前面写一些东西。


T1

主观难度:【1】

我是傻逼。注意到票款是可以拆出来算的,于是先不算票款对所有关键点跑多源最短路,每次询问加上即可。

时间复杂度:\(\mathrm{O} (n \log n + q)\),带一个 \(32\) 的常数。

#include <bits/stdc++.h>
#define llong long long
#define N 5003
#define M 10004
using namespace std;

#define bs (1<<20)
char buf[bs], *p1, *p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,bs,stdin),p1==p2)?EOF:*p1++)
template<typename T>
inline void read(T& x){
    x = 0; int w = 1;
    char ch = gc();
    while(ch < '0' || ch > '9'){
        if(ch == '-') w = -w;
        ch = gc();
    }
    while(ch >= '0' && ch <= '9')
        x = (x<<3)+(x<<1)+(ch^48), ch = gc();
    x *= w;
}
template<typename T, typename ...Args>
inline void read(T& x, Args& ...y){
    return read(x), read(y...);
}

int n, m, k, q;
int a[N]; llong p[N];

int to[M], nxt[M], head[N], gsiz; llong val[M];
#define mkarc(u,v,w) (++gsiz, to[gsiz]=v, val[gsiz]=w, nxt[gsiz]=head[u], head[u]=gsiz)

llong dis[N][32]; int vis[N][32];
typedef tuple<llong, int, int> Node;
priority_queue<Node, vector<Node>, greater<Node>> pq;
void dijkstra(){
    for(int i = 1; i <= n; ++i) 
        for(int j = 0; j < 32; ++j)
            dis[i][j] = (llong)1e18+3, vis[i][j] = false;
    for(int i = 1; i <= k; ++i)
        dis[a[i]][0] = 0, pq.emplace(0, a[i], 0);
    while(pq.size()){
        Node now = pq.top(); pq.pop();
        int u = get<1>(now), k = get<2>(now);
        if(vis[u][k]) continue;
        vis[u][k] = true;
        for(int i = head[u]; i; i = nxt[i]){
            int v = to[i];
            if(dis[u][k]+val[i] < dis[v][k]){
                dis[v][k] = dis[u][k]+val[i];
                pq.emplace(dis[v][k], v, k);
            }
            for(int j = 0; j < 5; ++j){
                if((k&(1<<j))) continue;
                llong w = val[i]-val[i]/10*(j+1);
                int l = k|(1<<j);
                if(dis[u][k]+w < dis[v][l]){
                    dis[v][l] = dis[u][k]+w;
                    pq.emplace(dis[v][l], v, l);
                }
            }
        }
    }
    return;
}

int main(){
    read(n, m, k);
    for(int i = 1; i <= k; ++i) read(a[i]), ++a[i];
    for(int i = 1; i <= m; ++i){
        int u, v; llong w;
        read(u, v, w), ++u, ++v;
        mkarc(v, u, w);
    }
    dijkstra();
    read(q);
    while(q--){
        int s; llong res = (llong)1e18+3;
        read(s, p[1], p[2], p[3], p[4], p[5]);
        ++s;
        for(int i = 0; i < 32; ++i){
            llong tmp = dis[s][i];
            for(int j = 0; j < 5; ++j){
                if(!(i&(1<<j))) continue;
                if(p[j+1] == -1) goto nxt;
                tmp += p[j+1];
            }
            res = min(res, tmp);
            nxt:;
        }
        if(res >= 1e18) puts("-1");
        else printf("%lld\n", res);
    }
    return 0;
}

T2

主观难度:【2-】

猜结论可做。(

很明显的反悔贪心,问题在于怎么排序。

我们假设交换 \(i, i+1\) 可以增大答案,那么有:

\[\begin{cases} s + x_i > l_{i+1} \\ s + x_{i+1} \le l_i \end{cases} \]

那么

\[\begin{cases} s > l_{i+1} - x_i \\ s \le l_i - x_{i+1} \end{cases} \]

整理得 \(l_{i+1} - x_i < l_i - x_{i+1}\),所以 \(l_{i+1} + x_{i+1} < l_i + x_i\)

于是我们按 \(l+x\) 排序即可。

#include <bits/stdc++.h>
#define llong long long
#define N 500005
using namespace std;

#define bs (1<<20)
char buf[bs], *p1, *p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,bs,stdin),p1==p2)?EOF:*p1++)
template<typename T>
inline void read(T& x){
    x = 0; int w = 1;
    char ch = gc();
    while(ch < '0' || ch > '9'){
        if(ch == '-') w = -w;
        ch = gc();
    }
    while(ch >= '0' && ch <= '9')
        x = (x<<3)+(x<<1)+(ch^48), ch = gc();
    x *= w;
}
template<typename T, typename ...Args>
inline void read(T& x, Args& ...y){
    return read(x), read(y...);
}

int n;
llong a[N], b[N]; int id[N];
llong lev, ans;

typedef pair<llong, llong> Node;
priority_queue<Node, vector<Node>, greater<Node>> pq1;
priority_queue<llong> pq2;

int main(){
    read(n);
    for(int i = 1; i <= n; ++i) read(a[i]);
    for(int i = 1; i <= n; ++i) read(b[i]);
    for(int i = 1; i <= n; ++i) id[i] = i;
    sort(id+1, id+n+1, [&](int o1, int o2){return a[o1]+b[o1]<a[o2]+b[o2];});
    for(int i = 1; i <= n; ++i){
        if(lev <= b[id[i]]){
            lev += a[id[i]];
            pq2.push(a[id[i]]), ++ans;
        }
        else if(pq2.size() && pq2.top() > a[id[i]]){
            lev += a[id[i]]-pq2.top();
            pq2.pop(), pq2.push(a[id[i]]);
        }
    }
    printf("%lld", ans);
    return 0;
}

T3

主观难度:【1+】

傻逼题。

T4

主观难度:【1+】

一个没脑子做法是

posted @ 2026-03-11 13:01  Hootime  阅读(3)  评论(0)    收藏  举报