[CCPC 2024 哈尔滨站] CCPC 2024 分站赛哈尔滨站重现赛 题解
P14803 [CCPC 2024 哈尔滨站] 在哈尔滨指路
直接模拟即可
#include <bits/stdc++.h>
using namespace std;
map<char,int> f;
void solve()
{
int n,x = 0,y = 0;
char op,c; int d;
cin >> n; n--;
cin >> op >> d;
cout << (n + 1) * 2 - 1 << " " << op << "\n";
cout << "Z " << d << "\n";
while(n--)
{
cin >> c >> d;
if(f[c] == 4 && f[op] == 1) cout << "L\n";
else if(f[c] == 1 && f[op] == 4) cout << "R\n";
else cout << (f[c] > f[op]? "R\n" : "L\n");
cout << "Z " << d << "\n";
op = c;
}
// cout.flush();
}
int main()
{
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
f['N'] = 1; f['E'] = 2; f['S'] = 3; f['W'] = 4;
int T; cin >> T;
while(T--) solve();
return 0;
}
2发罚时,死因:没看到“保证相邻两个指令中 d 不相同且不相反(北与南互相相反,西与东互相相反)。” ……
P14807 [CCPC 2024 哈尔滨站] 欢迎加入线上会议!
bfs 即可
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5,M = 5e5 + 5;
int n,m,k,a[N];
vector<int> G[N];
int main()
{
cin >> n >> m >> k;
for(int i = 1,x; i <= k; i++) cin >> x,a[x] = 1;
int u,v;
while(m--) cin >> u >> v,G[u].push_back(v),G[v].push_back(u);
if(n == k) { cout << "No\n"; return 0; }
int root = 0;
for(int i = 1; i <= n; i++) if(!a[i]) { root = i; break; }
vector<vector<int> > g;
queue<int> q; q.push(root); vector<bool> vis(n + 1); vis[root] = 1;
while(!q.empty())
{
int x = q.front(); q.pop();
if(a[x]) continue;
// cout << x << "\n";
vector<int> tp; tp.push_back(x);
for(int i : G[x]) if(!vis[i]) tp.push_back(i),q.push(i),vis[i] = 1;
if(tp.size() > 1) g.push_back(tp);
}
// cout << "bfs done.";
for(int i = 1; i <= n; i++) if(vis[i] == 0) { cout << "No\n"; return 0; }
cout << "Yes\n" << g.size() << "\n";
for(vector<int> p : g)
{
cout << p[0] << " " << p.size() - 1 << " ";
for(int i : p) if(i != p[0]) cout << i << " ";
cout << "\n";
}
return 0;
}
罚时一发,死因:没判他一个人也没法扩展。
P14811 [CCPC 2024 哈尔滨站] 农场经营
首先注意到有一下贪心:
- 把 \(m\) 给 \(w\) 最大的
- 把 \(m\) 给 \(w\) 最小的
第一个容易实现,不赘述:
ll s = 0,c = 0;
for(int i = 1; i <= n; i++)
s += a[i].l * a[i].w,c += a[i].l;
ll ans1 = s + a[n].w * (m - c);
第二个在实现中发现问题,把 \(m\) 给最小的意义是把空出来的 \(L_{min}\) 给 \(w_{max}\) 的。
但是 \(w_{max}\) 最多只能拿 \(R_{max}\) 个,剩余的应该分给 \(w_{sec}\)……以此类推。
我们发现可能存在一个 \(i\),\(w_i\) 可能不是最小的,但是 \(L_i\) 很大,即换成 \(w_{max}\) 时能换很多,于是还得枚举。
我们枚举换哪一个作物,发现这样是 \(O(n^2)\) 的,考虑优化。
注意到我们按照 \(L\) 升序排序后,能替换的 \(w\) 大的作物数量只会变多,维护一个 \(p\) 表示现在 \((p,n]\) 可以满(达到 \(R\)),\(p\) 能多余 \(L\),但达不到 \(R\),复杂度降到了 \(O(n \log n)\)。
然后可以愉快的通过了。
通过后笔者认为这是一道绿题,因为至少比P14810 [CCPC 2024 哈尔滨站] 新能源汽车难,但是一看题解就被二分解法无语了,关键是我的代码复杂度高时间复杂度还一样……
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 5;
ll n,m;
struct Type { ll w,l,r; } a[N];
bool cmp(Type x,Type y) { return x.w < y.w; }
bool cmp2(Type x,Type y) { return x.l < y.l; }
int main()
{
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> a[i].w >> a[i].l >> a[i].r;
sort(a + 1,a + n + 1,cmp);
ll s = 0,c = 0;
for(int i = 1; i <= n; i++)
s += a[i].l * a[i].w,c += a[i].l;
ll ans1 = s + a[n].w * (m - c);
ll ans2 = 0,sum = s;
sort(a + 1,a + n + 1,cmp2);
vector<array<ll,2> > g;
for(int i = 1; i <= n; i++) g.push_back({a[i].w,a[i].r - a[i].l});
sort(g.begin(),g.end());
int p = g.size() - 1;
for(int i = 1; i <= n; i++)
{
ll rest = a[i].l - a[i - 1].l;
if(i == 1) rest += m - c;
while(rest && p >= 0)
{
if(g[p][1] > rest) g[p][1] -= rest,sum += g[p][0] * rest,rest = 0;
else sum += g[p][0] * g[p][1],rest -= g[p][1],p--;
}
sum += a[i - 1].w * a[i - 1].l;
sum -= a[i].w * a[i].l;
ans2 = max(ans2,sum);
}
ll ans = max(ans1,ans2);
cout << ans << "\n";
return 0;
}
P14810 [CCPC 2024 哈尔滨站] 新能源汽车
有显然贪心策略:尽量取即将加满的
具体化:按照距离排序,从近到远取
特判“都取完了”:把永远不会充电的电瓶初始电量和记为一个 res,减 res 即可
具体化:用优先队列实现,记录每个位置的 nxt,每次充电时把 nxt 放入队列。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
ll n,m,a[N],v[N];
ll d[N],t[N],nxt[N];
void solve()
{
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> a[i],v[i] = a[i];
for(int i = 1; i <= m; i++) cin >> d[i] >> t[i];
vector<int> id(n + 1);
for(int i = m; i >= 1; i--)
{
nxt[i] = id[t[i]];
id[t[i]] = i;
}
priority_queue<array<ll,2>,vector<array<ll,2> >,greater<array<ll,2> > > q;
ll res = 0;
for(int i = 1; i <= n; i++) if(id[i]) q.push({d[id[i]],i}); else res += v[i],v[i] = 0;
for(int i = 1; i <= m; i++)
{
ll dis = d[i] - d[i - 1];
while(!q.empty() && dis)
{
int x = q.top()[1];
if(dis >= v[x]) dis -= v[x],v[x] = 0,q.pop();
else v[x] -= dis,dis = 0;
}
if(dis)
{
if(dis > res) { for(int i = 1; i <= n; i++) assert(v[i] == 0); cout << d[i] - (dis - res) << "\n"; return; }
res -= dis,dis = 0;
}
// for(int j = 1; j <= n; j++) cout << v[j] << " "; cout << "\n";
v[t[i]] = a[t[i]]; if(nxt[i]) q.push({d[nxt[i]],t[nxt[i]]}); else res += v[t[i]],v[t[i]] = 0;
while(!q.empty() && q.top()[0] <= d[i]) q.pop();
// cout << t[i] << ":\n";
// for(int j = 1; j <= n; j++) cout << v[j] << " "; cout << "\n";
}
ll ans = res;
for(int i = 1; i <= n; i++) ans += v[i];
cout << ans + d[m] << "\n";
}
int main()
{
int T; cin >> T;
while(T--) solve();
return 0;
}
本文来自博客园,作者:cshur,转载请注明原文链接:https://www.cnblogs.com/cshur/articles/19377075。
cshur 转载请注明作者

浙公网安备 33010602011771号