这一场的题目都很有趣。我比赛的时候第三题样例画错,然而题目也理解错了,所以就居然算出正解。这太巧合了,打的也很烂。心态也很糟糕。还有第一题,读题漏信息真的好多。就下次思维别这么跳跃吧。然后T2(有趣的题目)一开始想就想错,还感觉很对就离谱。我没有用题目已知条件映射的数学柿子来变形,而是自己凭感觉凑与推。我觉的我目前的水平想对思路真的很难。第四题,数据结构第一步的转换都想不到,更别说后面的板子。这个转化也挺有趣的。
T1 饥饿的狐狸
-
题意:你有块饼干每块温度,你还有的水,你的狐狸喜欢舌间的冷热刺激,每次吃饼干的美味度是上一次于这一次温度差的绝对值。问吃完饼干的最大和最小美味值。
-
思路:
-
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5;
ll t[N];
int main() {
int n;ll w;
scanf("%d%lld",&n,&w);
for(int i=1;i<=n;i++) scanf("%lld",&t[i]);
sort(t+1,t+1+n);
printf("%lld ",max(0ll,w-t[1])+max(0ll,t[n]-w));
int l=1,r=n; ll mx1=0,mx2=0,lst=w;
for(int i=1;i<=n;i++) {
if(i&1) mx1+=max(abs(t[l]-w),abs(t[l]-lst)),lst=t[l++];
else mx1+=max(abs(t[r]-w),abs(t[r]-lst)),lst=t[r--];
}
l=1,r=n,lst=w;
for(int i=1;i<=n;i++) {
if(i&1) mx2+=max(abs(t[r]-w),abs(t[r]-lst)),lst=t[r--];
else mx2+=max(abs(t[l]-w),abs(t[l]-lst)),lst=t[l++];
}
printf("%lld",max(mx1,mx2));
return 0;
}
T2保险箱
- 题意:略
这道题我后面会写的很啰嗦,因为很有趣
- 思路:我们考虑到一个显然的性质: 为可以打开的,我考场上就想到这点然后就想偏了。
首先这道题就两种条件(一个正确的,和一堆错误的),条件越少,我们就要将其挖掘越深。
我们设最后可行的集合为S.
- 正确
c为一定可行的解
因此已经能确定的最小的S内元素为
第一个重要性质: - 错误
第二个条件:
答案为
ps.为什么d的倍数不能取模,因为一开始d的定义就直接表示最终状态的gcd
因此我们的需求是最小的
然后我们先将 ,
此时内只有种也有的因子,我们将其从中筛掉,此时便为中的最小因子。
具体实现中我们发现最多20个质因子,把它们筛出来,每个筛的时候,用map记忆化搜索一下。
复杂度为上限约 - 代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5;
ll p[N],c[N],m[N],tot;
set<ll> S;
map<ll,bool>mp;
ll gcd(ll u,ll v) {
if(!v) return u;
return gcd(v,u%v);
}
void dfs(ll x) {
if(mp[x])return; mp[x]=1;
for(int i=1;i<=tot;i++) if(x%p[i]==0)dfs(x/p[i]);
}
int main() {
ll n;int k;
scanf("%lld%d",&n,&k);
for(int i=1;i<=k;i++) scanf("%lld",&m[i]);
m[k]=gcd(m[k],n);
for(int i=1;i<k;i++) m[i]=gcd(m[i],m[k]);
ll x=m[k];
for(ll i=2;i*i<=x;i++) {
if(x%i==0) {
p[++tot]=i;
while(x%i==0) {x/=i;}
}
}
if(x>1) {p[++tot]=x;}
for(int i=1;i<k;i++)dfs(m[i]);
ll i;
for(i=1;i*i<=m[k];i++) if(m[k]%i==0&&!mp[i]) {printf("%lld",n/i);return 0;}
for(;i;i--) if(m[k]%i==0&&!mp[m[k]/i]) {printf("%lld",n/(m[k]/i));return 0;}
return 0;
}
Chase
- 题解:
显然拿一维记录剩余磁铁数
表示从到子树内部最大,表示从子树内到。
转移见代码
为什么这样?因为走的方向会影响,比如你放磁铁会影响你的父亲而不是孩子。(考试上就tm没想全)
写代码中有一些细节:
1.更新注意不能重,然后不能到达两个相同的子树
2.按1来写,要正反来两遍
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
const int M=105;
int n,V,head[N<<1],to[N<<1],nxt[N<<1],ecnt;
ll sum[N],ans,val[N],t[N][M],p[N][M],mx2[M];
void add_edge(int u,int v) {nxt[++ecnt]=head[u];to[ecnt]=v;head[u]=ecnt;}
void dfs(int u,int fa) {
int tp=0,st[N];
for(int j=1;j<=V;j++) t[u][j]=sum[u]-val[fa],p[u][j]=sum[u];
for(int i=head[u];i;i=nxt[i]) {
int v=to[i];
if(v==fa)continue;
dfs(v,u);st[++tp]=v;
for(int j=1;j<=V;j++)ans=max(ans,p[u][j]+t[v][V-j]);
for(int j=1;j<=V;j++) {
t[u][j]=max(t[u][j],max(t[v][j],t[v][j-1]+sum[u]-val[fa]));
p[u][j]=max(p[u][j],max(p[v][j],p[v][j-1]+sum[u]-val[v]));
}
}
for(int j=1;j<=V;j++) t[u][j]=sum[u]-val[fa],p[u][j]=sum[u];
for(int i=tp;i>=1;i--) {
int v=st[i];
for(int j=1;j<=V;j++)ans=max(ans,p[u][j]+t[v][V-j]);
for(int j=1;j<=V;j++) {
t[u][j]=max(t[u][j],max(t[v][j],t[v][j-1]+sum[u]-val[fa]));
p[u][j]=max(p[u][j],max(p[v][j],p[v][j-1]+sum[u]-val[v]));
}
}
ans=max(ans,max(t[u][V],p[u][V]));
}
int main() {
scanf("%d%d",&n,&V);
for(int i=1;i<=n;i++) scanf("%lld",&val[i]);
for(int i=1;i<n;i++) {
int u,v;
scanf("%d%d",&u,&v);
sum[u]+=val[v],sum[v]+=val[u];
add_edge(u,v),add_edge(v,u);
}
dfs(1,0);
printf("%lld",ans);
return 0;
}
Election
-
思路:考虑这样一种简单的贪心,我们从前向后扫一遍,如果前缀小于 0 就删掉当前字符,在从后向前扫一遍即可。
-
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
char ch[N];
int Q,n,a[N],s[N];
struct seg {int l,r,mx,lx,rx,sum;}T[N<<2];
void P_up(int x) {
int ls=x<<1,rs=x<<1|1;
T[x].sum=T[ls].sum+T[rs].sum;
T[x].rx=max(T[rs].rx,T[rs].sum+T[ls].rx);
T[x].lx=max(T[ls].lx,T[ls].sum+T[rs].lx);
T[x].mx=max(T[ls].rx+T[rs].lx,max(T[ls].mx,T[rs].mx));
}
void Build(int x,int l,int r) {
T[x]=(seg){l,r,0,0,0};
if(l==r) {T[x].lx=T[x].rx=T[x].mx=a[l];T[x].sum=a[l];return;}
int mid=(l+r)>>1;
Build(x<<1,l,mid),Build(x<<1|1,mid+1,r);
P_up(x);
}
seg Mx(int x,int l,int r) {
if(l<=T[x].l&&T[x].r<=r) return T[x];
int mid=(T[x].l+T[x].r)>>1,res=0;
seg u,v,w;
if(l<=mid) {
u=Mx(x<<1,l,r);
if(r<=mid) return u;
}
if(r>mid) {
v=Mx(x<<1|1,l,r);
if(l>mid) return v;
}
w.sum=u.sum+v.sum;
w.rx=max(v.rx,v.sum+u.rx);
w.lx=max(u.lx,u.sum+v.lx);
w.mx=max(u.rx+v.lx,max(u.mx,v.mx));
return w;
}
int main() {
scanf("%d",&n);
scanf("%s",ch);
for(int i=0;i<n;i++) a[i+1]=(ch[i]=='C')?1:-1;
for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i];
Build(1,1,n);
scanf("%d",&Q);
while(Q--) {
int l,r;
scanf("%d%d",&l,&r);
int ss=s[r]-s[l-1];
printf("%lld\n",max(Mx(1,l,r).mx,0)-ss);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人