模拟赛Day1
模拟赛Day1
状态不好,暴力都没打全(QAQ),暴力打全后再去想正解应该是最优解。
-取餐号
思路
没什么可说的,是一道水题,欧拉筛筛一下直接过。当时还以为题很简单。
时间复杂度
点击查看代码
`#include<bits/stdc++.h>
using namespace std;
int n,m,prime[5000000],tot,v[5000000];
int main()
{
cin>>n>>m;
for(int i=2;i<=n;i++)
{
if(!v[i])
{
v[i]=i;
prime[++tot]=i;
}
for(int j=1;j<=tot;j++)
{
if(prime[j]>v[i]||prime[j]*i>n)
break;
v[i*prime[j]]=prime[j];
}
}
cout<<tot<<' '<<prime[m];
return 0;
}`
-堆人塔
- 40分
很简单,dfs暴力模拟就可。(考场上傻了,暴力都没写对)。
但貌似数据有点水,写暴力能拿50分。
时间复杂度
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,a[200000],d[200000];
void dfs(int l,int r,int ds)
{
if(l>r)
return;
int maxx=0,id;
for(int i=l;i<=r;i++)
if(a[i]>maxx)
{
maxx=a[i];
id=i;
}
d[id]=ds;
dfs(l,id-1,ds+1);
dfs(id+1,r,ds+1);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
dfs(1,n,0);
for(int i=1;i<=n;i++)
printf("%d ",d[i]);
return 0;
}
- 100分
思考一下,题目中其实让求的就是一段段区间的最大值,而区间最值问题有一个很著名的算法 —— ST表
ST表可以在
时间复杂度
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5;
int n,a[N],f[30][N],t[N],ans[N];
void dfs(int l,int r,int cs)
{
if(l>r||l==0||r==n+1)
return;
int k=log2(r-l+1);
ans[t[max(f[k][l],f[k][r-(1<<k)+1])]]=cs;
dfs(l,t[max(f[k][l],f[k][r-(1<<k)+1])]-1,cs+1);
dfs(t[max(f[k][l],f[k][r-(1<<k)+1])]+1,r,cs+1);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
f[0][i]=a[i];
t[a[i]]=i;
}
for(int i=1;i<=log2(n);i++)
for(int j=1;j<=n-(1<<i)+1;j++)
f[i][j]=max(f[i-1][j],f[i-1][j+(1<<(i-1))]);
dfs(1,n,0);
for(int i=1;i<=n;i++)
printf("%d ",ans[i]);
return 0;
}
-钦定IOI选手
- 20分
一道动态中位数问题,对于
时间复杂度
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,k,a[200000],maxx;
priority_queue<int> q2;
priority_queue<int,vector<int>,greater<int> > q1;
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n-k+1;i++)
{
for(int j=i;j<=n;j++)
{
q1.push(a[j]);
if(q1.size()-q2.size()==2)
{
q2.push(q1.top());
q1.pop();
}
if(!q2.empty()&&q1.top()<q2.top())
{
q2.push(q1.top());
q1.pop();
q1.push(q2.top());
q2.pop();
}
if(j-i+1>=k)
{
if(!((j-i+1)%2))
maxx=max(maxx,q2.top());
else
maxx=max(maxx,q1.top());
}
}
while(!q1.empty())
q1.pop();
while(!q2.empty())
q2.pop();
}
printf("%d",maxx);
return 0;
}
- 100分
中位数有一个经典的二分做法。可以二分答案,二分中位数,把大于等于中位数的赋值为
再维护一个前缀和,这样,前缀和大于
这种二分思路很重要!
时间复杂度
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,k,a[200000],b[200000],maxx,l=1,r,mid,wfl[200000],sum[200000],minn;
bool check(int x)
{
minn=0x3f3f3f3f;
for(int i=1;i<=n;i++)
{
if(a[i]>=b[x])
wfl[i]=1;
else
wfl[i]=-1;
sum[i]=sum[i-1]+wfl[i];
if(i>k)
minn=min(minn,sum[i-k]);
if(sum[i]-minn>0)//一定要注意=0时,sum[i]-minn的中位数不为mid!!!
return 1;
}
return 0;
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+n+1);
r=n;
while(l+1<r)
{
mid=(l+r)/2;
if(check(mid))
l=mid;
else
r=mid;
}
if(check(r))
printf("%d",b[r]);
else
printf("%d",b[l]);
return 0;
}
-攻打恶魔之巅
把每一个台阶看做一个点,它连向的点有两类,一类是步长,一类是传送门。
这不分层图最短路嘛。虽然考试时完全不知道这是个啥。
构图后可以直接跑一遍
分层图最短路一般模型:在图上,有k次机会可以直接通过一条边,问起点与终点之间的最短路径。
-30分
普通
时间复杂度
-75分
时间复杂度
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll qr()
{
ll x=0,f=0;char ch=0;
while(!isdigit(ch)) {f|=ch=='-';ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return f? -x:x;
}
int n,m,k;
const ll maxn=500100;
struct fun
{
ll y,v,nxt;
}edge[25000100];
ll link[maxn];
ll len;
ll a[maxn];
ll dis[maxn][30];
bool vis[maxn][30];
ll ans=2e9;
struct node
{
int pos,vav;
};
deque <node> que;
void insert(int xx,int yy,int val)
{
edge[++len].nxt=link[xx];
link[xx]=len;
edge[len].y=yy;
edge[len].v=val;
}
void init()
{
n=qr();m=qr();k=qr();
for(int i=1;i<=n;i++)
{
a[i]=qr();
}
for(int i=1;i<=n;i++)
{
for(int j=max(i-m,1);j<=min(i+m,n);j++)
{
insert(i,j,1);
}
}
}
void DIJ()
{
memset(dis,10,sizeof(dis));
que.push_back((node){1,0});
dis[1][0]=0;
while(!que.empty())
{
node py=que.front();
que.pop_front();
if(vis[py.pos][py.vav]) continue;
vis[py.pos][py.vav]=1;
if(a[py.pos]&&py.vav!=k)
{
if(!vis[a[py.pos]][py.vav+1]&&dis[a[py.pos]][py.vav+1]>dis[py.pos][py.vav])
{
dis[a[py.pos]][py.vav+1]=dis[py.pos][py.vav];
que.push_front((node){a[py.pos],py.vav+1});
}
}
for(int i=link[py.pos];i;i=edge[i].nxt)
{
if(!vis[edge[i].y][py.vav]&&dis[edge[i].y][py.vav]>dis[py.pos][py.vav]+edge[i].v)
{
dis[edge[i].y][py.vav]=dis[py.pos][py.vav]+edge[i].v;
que.push_back((node){edge[i].y,py.vav});
}
}
}
}
void work()
{
DIJ();
for(int i=0;i<=k;i++)
{
ans=min(ans,dis[n][i]);
}
cout<<ans;
}
int main()
{
init();
work();
}
-100分
因为边权要么为
时间复杂度
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,m,k;
int t[500010];
struct nn
{
int now;
int hp;
int d;
} ;
queue<nn> q;
int f[500001][21];
int ans=1e9;
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++){
scanf("%d",&t[i]);
}
memset(f,0x7f,sizeof(f));
f[1][k]=0;
q.push((nn){1,0,k});
while(!q.empty()){
int nw=q.front().now;
int h=q.front().hp;
int dj=q.front().d;
q.pop();
if(f[nw][dj]<h){
continue;
}
f[nw][dj]=h;
if(nw==n){
ans=min(ans,h);
continue;
}
if(t[nw]&&dj>=1){
if(f[t[nw]][dj-1]>h){
f[t[nw]][dj-1]=h;
q.push((nn){t[nw],h,dj-1});
}
}
int l=max(nw-m,1), r=min(nw+m,n);
for(int i=l;i<=r;i++){
if(f[i][dj]>h+1){
f[i][dj]=h+1;
q.push((nn){i,h+1,dj});
}
}
}
cout<<ans;
return 0;
}
-抉择
-10分
送分,判断
-100分
不会,回来有缘再补~
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通