碎碎念:这场有点水,原和板子太多了,写着写着就跑去睡觉了QWQ
目录
A-日历游戏
思路:找规律,可发现大部分情况下日期+月数为奇数时先手必胜,有两个特殊日期9.30和11.30,加日就能避免操作后奇偶性变化保证必胜。
void solve()
{
int x,y,z;
std::cin>>x>>y>>z;
if((y==9&&z==30)||(y==11&&z==30)||(y+z)%2==0) std::cout<<"YES\n";
else std::cout<<"NO\n";
}
B-学生分组
思路:总人数<组数*L和总人数>组数*R(即判断平均数是否在区间里)输出-1
然后就是多出的人数去补缺少的人数,取max即可
注意开longlong,代码#define int long long 了
void solve()
{
int n;
std::cin>>n;
std::vector<int>a(n,0);
i64 res=0;
for(auto &x:a) std::cin>>x,res+=x;
int l,r;
std::cin>>l>>r;
if(res<n*l||res>n*r)
{
std::cout<<"-1\n";
return;
}
int b=0,c=0;
for(int i=0;i<n;i++)
{
if(a[i]<l) b+=l-a[i];
else if(a[i]>r) c+=a[i]-r;
}
std::cout<<std::max(b,c)<<'\n';
}
C-关押罪犯
换上原题面
思路:种类(扩展域)并查集板子题,贪心的从大到小排序冲突值,优先处理冲突值高的,维护两个集合,若x与y冲突,则合并(x,y+n)和(x+n,y),直至枚举到的x,y在已经在一个集合中了就可以确定冲突值了,注意没冲突时冲突值为0
void solve()
{
int n,m;
std::cin>>n>>m;
std::vector<std::tuple<i64 ,int ,int >>g;
for(int i=0;i<m;i++)
{
i64 u,v,w;
std::cin>>u>>v>>w;
g.pb({w,u,v});
}
std::sort(g.begin(), g.end(),std::greater<>());
DSU dsu(2*n);
i64 res=0;
for(int i=0;i<m;i++)
{
auto [w,u,v]=g[i];
if(dsu.find(u)==dsu.find(v)||dsu.find(u+n)==dsu.find(v+n))
{
res=w;
break;
}
dsu.merge(u+n,v);
dsu.merge(v+n,u);
}
std::cout<<res<<'\n';
}
D-区间问题1
思路:本来想上线段树的,但看到过题数似乎有点多了就猜数据可能水了,交一发暴力还真过了
void solve()
{
int n;
std::cin>>n;
std::vector<int>a(n,0);
for(auto &x:a) std::cin>>x;
int q;
std::cin>>q;
while (q--)
{
int op;
std::cin>>op;
if(op==1)
{
int l,r,c;
std::cin>>l>>r>>c;
l--,r--;
for(int i=l;i<=r;i++) a[i]+=c;
}
else
{
int x;
std::cin>>x;
x--;
std::cout<<a[x]<<'\n';
}
}
}
E-哥德巴赫猜想
思路:暴力搞了一下,赛后看别人代码发现可以先筛出5e4的质数,然后set维护第三个数
void solve()
{
auto check=[&](i64 x)->bool
{
for(int i=2;i<=x/i;i++)
if(x%i==0) return false;
return true;
};
i64 x;
std::cin>>x;
if(check(x-4))
{
std::cout<<"2 2 "<<x-4<<'\n';
return;
}
for(int i=3;i<x;i++)
{
if((i%2)!=0&&check(i))
for (int j=i;j<x;j++)
if((j%2)!=0&&check(j))
if(check(x-i-j))
{
std::cout<<i<<" "<<j<<" "<<x-i-j<<'\n';
return;
}
}
}
F-小美想跑步
思路:有向图中起点到到其他点的最短距离,和其他点到起点的最短距离
void solve()
{
int n, m;
std::cin >> n >> m;
DIJ dij1(n), dij2(n);
for (int i = 0; i < m; i ++)
{
int u, v, w;
std::cin >> u >> v >> w;
dij1.add(u, v, w);
dij2.add(v, u, w);
}
dij1.dijkstra(1);
dij2.dijkstra(1);
i64 ans = 0;
for (int i = 2; i <= n; i ++)
ans += dij1.dis[i] + dij2.dis[i];
std::cout << ans << '\n';
}
G-爬楼梯
思路:简单dp f[i]=f[i-1]+f[i-2]+f[i-3]
void solve()
{
int n;
std::cin>>n;
std::vector<int>f(n+1,0);
f[0]=1,f[1]=2,f[2]=4;
for(int i=3;i<n;i++) f[i]=((f[i-1]+f[i-2])%mod+f[i-3])%mod;
std::cout<<f[n-1]<<'\n';
}
H-区间问题2
思路:ST表
void solve()
{
int n;
std::cin>>n;
std::vector<std::vector<int>>f(n+1,std::vector<int>(20,0));
for(int i=1;i<=n;i++) std::cin>>f[i][0];
for(int j=1;j<=20;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
f[i][j]=std::max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
int q;
std::cin>>q;
while (q--)
{
int l,r;
std::cin>>l>>r;
int k=log2(r-l+1);
std::cout<<std::max(f[l][k],f[r-(1<<k)+1][k])<<'\n';
}
}
I-小美想打音游
思路:中位数贪心
void solve()
{
int n;
std::cin>>n;
std::vector<int>a(n,0);
for(auto &x:a) std::cin>>x;
std::sort(a.begin(), a.end());
if(n&1)
{
int x=n/2;
i64 res=0;
std::cerr<<a[x]<<'\n';
for(int i=0;i<n;i++) res+=std::abs(a[i]-a[x]);
std::cout<<res+1<<'\n';
}
else
{
i64 res=0;
int x=n/2;
int mid=(a[x]+a[x-1])/2;
std::cerr<<a[x]<<' '<<a[x-1]<<'\n';
std::cerr<<a[mid]<<'\n';
for(int i=0;i<n;i++) res+=std::abs(a[i]-mid);
std::cout<<res+1<<'\n';
}
}
J-平方根
思路:签到题
void solve()
{
i64 n;
std::cin>>n;
std::cout<<(i64)__builtin_sqrt(n)<<'\n';
}
K-小美想游泳
思路:堆优化的dij维护路径的最大值
void solve()
{
int n,m;
std::cin>>n>>m;
DIJ dij(n);
for(int i=0;i<m;i++)
{
int u,v,w;
std::cin>>u>>v>>w;
dij.add(u,v,w);
dij.add(v,u,w);
}
int s,t;
std::cin>>s>>t;
dij.dijkstra(s);
std::cout<<dij.dis[t]<<'\n';
}