江湖人是过河卒 路是不归路 -- csp-s 2025 游记
江湖人是过河卒 路是不归路 -- csp-s 2025 游记
总结: 打铁了, 但是龙胆紫说 "江湖人是过河卒 路是不归路", 所以我不会 exit 的.
day \(-1\)
睡不着, 打开 b 站看人直播 vp cf/atc, 我 vp div4 被炸死了.
感觉要寄.
day \(0\)
火车上用耳机听着龙胆紫迷迷糊糊睡着了, 万幸的是电脑没丢. 左边坐的是 sdzb 某校的 oi 教练.
中午在一个离谱的店里吃了没有京味儿的炸酱面, 遇见了 qwqSW 老师, rp++.
晚上看考场, 和巨佬 SmartWind 在同一个考场, rp++.
回宾馆在很多群里发了 rp-=~inf+1;.
day \(0.5\)
想起来 2ptr algo 还没学, 贺了几个黄题.
problem:洛谷-P1638 problem:洛谷-P3029
day \(1\)
14:30 才发压缩包密码, 人杰地灵. 听说 j 组是 上善若水, ccf 最近在修仙吗?
先大致浏览了一遍 statement, a 是贪婪没想到怎么贪, b 是个诡异的最小导出树有点像分层图, c 是弦论压根不会, d 是 dp.
注意到 d 有几个测试点是 pure \(s_{i}==1\) 的, 我怀疑输出的就是取模后的阶乘. 大概不到半小时写完了缺省源和一个 ll fctrl(ll), 运行发现并不是取模的阶乘, 于是放弃.
由于贪婪是我非常薄弱的算法, 于是我选择了写 b.
有些数据点的乡镇的点权为 \(0\), 那么我们说在这个乡镇产生了作用当且仅当在最小导出树里不是叶子, 可以证明.
于是先 kruskal 出 mst, 判断一个边如果某个顶点在 mst 里的度为 \(1\) 则认为是叶子, 此时判断是否是乡镇, 如果是乡镇就不管这条边, 否则累加这条边.
这个用 \(deg_{x}==1\) 判断叶子的方法还是某次模拟赛我把 bfs 判叶子写炸了后某大神教我的, 真是一个酣畅淋漓的判叶子啊.
不是说不会贪婪算法吗, kruskal mst 不是贪婪吗? 为什么对于最短路和 mst 以及 tarjan 算法如此熟练?
代码大赏 (这是考后写的, 场上写的码风非常差).
#include<cmath>
#include<climits>
#include<cstdbool>
#include<cstddef>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<deque>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<tuple>
#include<vector>
using lf=double;
using us=size_t;
using ll=ptrdiff_t;
constexpr ll inf=0x3f3f3f3f3f3f3f3fl;
constexpr ll mod=0x3b800001l;
constexpr ll ver=1l<<14;
typedef struct _vtx vtx;
struct _vtx{
vtx *top;
ll val,deg;
void add_edge(vtx*,ll);
auto fnd(void)->vtx*;
} v[ver];
std::vector<std::tuple<vtx*,vtx*,ll,_Bool>>e;
void vtx::add_edge(vtx *y,ll z){
e.emplace_back(this,y,z,0);
}
auto vtx::fnd(void)->vtx*{
if(top==NULL)
return this;
else return top=top->fnd();
}
auto kruskal(ll n,ll n2)->ll{
std::sort(e.begin(),e.end(),[](std::tuple<vtx*,vtx*,ll,_Bool>&f,std::tuple<vtx*,vtx*,ll,_Bool>&g){
return std::get<2>(f)<std::get<2>(g);
}); for(auto &[x,y,z,f]:e){
if(x->fnd()==y->fnd())
continue;
x->deg++,y->deg++,f=1;
x->fnd()->top=y->fnd();
} ll s=0;
for(auto &[x,y,z,f]:e){
if(f==0)
continue;
if(v+n<x&&x->deg==1)
continue;
if(v+n<y&&y->deg==1)
continue;
s+=z;
} return s;
}
void solve(void){
ll n,m,n2;
std::cin>>n>>m>>n2;
while(m--){
ll x,y,z;
std::cin>>x>>y>>z;
v[x].add_edge(v+y,z);
v[y].add_edge(v+x,z);
} for(ll x=n+1;x<=n+n2;x++){
std::cin>>v[x].val;
for(ll y=1;y<=n;y++){
ll z;
std::cin>>z;
v[x].add_edge(v+y,z);
v[y].add_edge(v+x,z);
}
} std::cout<<kruskal(n,n2)<<"\n";
}
auto main(void)->signed{
freopen("road.in","r",stdin);
freopen("road.out","w",stdout);
std::ios::sync_with_stdio(0);
std::cin.tie(0),std::cout.tie(0);
ll t=1;
// std::cin>>t;
while(t--)
solve();
return 0;
}
估分是裸 kruskal 的 \(4*4=16\) 分再加上乡镇权值为 \(0\) 的测试点的 \(8*4=32\) 分就是 \(48\) 分, 洛谷确实给了 \(48\), 希望 freopen("road.in","r",stdin); 不要出事.
不要致敬 Wild_Donkey 的 freopen("julian3.in","r",stdin); 了.
于是回来看 a, 此时还剩两个小时.
在刚仔细看题时认为特殊性质之均匀随机是无用的, 但注意到直接累计每个 std::max({a[i][1],a[i][2],a[i][3]}) 并输出就能得分, 于是有了 \(10\) 分.
那么特殊性质之 \(a_{i,2}==a_{i,3}==0\) 也是比较容易的, std::sort(a+1,a+n+1,cmp); 后累计前半段输出即可, 又到手了 \(5\) 分.
特殊性质之 \(a_{i,3}==0\) 是非常有难度的, 我想了很久也没想法.
注意到有 \(n==200\) 的暴力分 \(45\) 分, 想了半小时 \(O(n^{2})\) 和 \(O(n^{3})\) 都没有思路, 莫名的一直在往状压上想, 甚至想到了枚举 \(S\subset U\) 后枚举 \(T\subset(U\setminus S)\) 这样诡异的状压.
可得这种状压的时间复杂度为 \(O(3^{n})\), 和搜索没有什么区别, 甚至迭代比递归更快.
然而这样的状压其实就不如搜索了, 于是在最后 \(15\) 分钟写了个搜索.
dfs 也是好歹有 \(20\) 分, 加上刚才两个特殊性质 (另一个特殊性质没想出来) 加起来的 \(15\) 分, 获得了 \(35\) 分.
代码大赏 (这也是赛后重写的).
#include<cmath>
#include<climits>
#include<cstdbool>
#include<cstddef>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<deque>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<tuple>
#include<vector>
using lf=double;
using us=size_t;
using ll=ptrdiff_t;
constexpr ll inf=0x3f3f3f3f3f3f3f3fl;
constexpr ll mod=0x3b800001l;
auto dfs(ll d,std::vector<std::tuple<ll,ll,ll>>&a,ll n,ll f,ll g,ll h,ll s){
if(d==n)
return s;
auto [x,y,z]=a[d];
ll v=f<n>>1?dfs(d+1,a,n,f+1,g,h,s+x):0;
v=std::max(v,g<n>>1?dfs(d+1,a,n,f,g+1,h,s+y):0);
v=std::max(v,h<n>>1?dfs(d+1,a,n,f,g,h+1,s+z):0);
return v;
}
void solve(void){
ll n;
std::cin>>n;
if(200<n){
ll s=0;
_Bool jqk=1;
std::vector<std::tuple<ll,ll,ll>>a(n);
for(auto &[x,y,z]:a)
std::cin>>x>>y>>z,s+=std::max({x,y,z}),jqk&=y==0&&z==0;
if(jqk==0){
std::cout<<s<<"\n";
return;
} std::sort(a.rbegin(),a.rend());
s=0;
for(ll t=0;t<a.size()>>1;t++)
s+=std::get<0>(a[t]);
std::cout<<s<<"\n";
return;
} std::vector<std::tuple<ll,ll,ll>>a(n);
for(auto &[x,y,z]:a)
std::cin>>x>>y>>z;
std::cout<<dfs(0,a,n,0,0,0,0)<<"\n";
}
auto main(void)->signed{
freopen("club.in","r",stdin);
freopen("club.out","w",stdout);
std::ios::sync_with_stdio(0);
std::cin.tie(0),std::cout.tie(0);
ll t=1;
std::cin>>t;
while(t--)
solve();
return 0;
}
计算分数 \(35+48+0+0=83\), 于是结局就是打铁了.
出考场时和 SmartWind 交流, SmartWind 认为是 黄蓝紫紫, 我希望是 绿蓝紫紫.
day \(2\)
火车上看着窗外的农田和公路飞速后退, 听着龙胆紫的 cypher, 莫名的想睡觉, 于是睡觉.
注意到洛谷给的颜色是 绿蓝紫紫.
day \(3\)
发现洛谷把颜色降到了 黄蓝紫紫, 非常生气.
写了游记.

浙公网安备 33010602011771号