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+】
一个没脑子做法是

浙公网安备 33010602011771号