2021-10-04国庆集训模拟赛

本文介绍了三个算法问题的解决方案:玩具谜题、神奇的幻方和蚯蚓问题。针对每个问题,分别给出了C++代码实现,并对算法思路进行了说明。此外,还讨论了在解决列队问题时遇到的挑战和解决方案,展现了对复杂问题的分析和编程能力。
摘要由CSDN通过智能技术生成


1、玩具谜题

算法思路:模拟
估分:100;
实得:100;
代码:

#include<bits/stdc++.h>
using namespace std;
const int N=100005;
int n,m,di[N],a[N],s[N]; 
string na[N];
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		cin>>di[i]>>na[i];
	for(int i=1;i<=m;i++)
	    cin>>a[i]>>s[i];
	int t=1;
	for(int i=1;i<=m;i++){
		if( (a[i]==0&&di[t]==0) || (a[i]==1&&di[t]==1) ){
			if(t>s[i]){
				t=t-s[i];
				continue;
			}
			if(t<=s[i])
			   t=t+n-s[i];
			continue;
		}
		if( (a[i]==0&&di[t]==1) || (a[i]==1&&di[t]==0) ){
			t=t+s[i];
			if(t>n)
			   t=t-n;
			continue;
		}
    }
    cout<<na[t]<<endl;
    return 0;
}

2、神奇的幻方

算法思路:模拟
估分:100
实得:100
代码:

#include<bits/stdc++.h>
using namespace std;
const int N=50;
int a[N][N],n; 

struct shu{
	int h,l;
}s[N*N];

int main(){
	cin>>n;
	a[1][n/2+1]=1;
	s[1].h=1;
	s[1].l=n/2+1;
	for(int k=2;k<=n*n;k++){
		if(s[k-1].h==1&&s[k-1].l!=n){
		   s[k].h=n;
		   s[k].l=s[k-1].l+1;
		   a[s[k].h][s[k].l]=k;
		}
		if(s[k-1].h!=1&&s[k-1].l==n){
		   s[k].h=s[k-1].h-1;
		   s[k].l=1;
		   a[s[k].h][s[k].l]=k;
		}
		if(s[k-1].h==1&&s[k-1].l==n){
		   s[k].h=s[k-1].h+1;
		   s[k].l=s[k-1].l;
		   a[s[k].h][s[k].l]=k;
	    }	
		if(s[k-1].h!=1&&s[k-1].l!=n){
		   if(a[s[k-1].h-1][s[k-1].l+1]==0&&s[k-1].h-1>0&&s[k-1].l+1<=n){
		   	  s[k].h=s[k-1].h - 1;
		   	  s[k].l=s[k-1].l + 1;
		   }
		   else{
		   	  s[k].h=s[k-1].h+1;
		   	  s[k].l=s[k-1].l;
		   }
		   a[s[k].h][s[k].l]=k;
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++)
		    cout<<a[i][j]<<" ";
		cout<<endl;
	}
	return 0;
}

3、蚯蚓

算法思路:队列or优先队列or二叉堆?可惜我不会这个
估分:0;
实得分数:0;
正解(洛谷):

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 100;
inline int read(){
	int x = 0;char c = getchar();
	while(!isdigit(c))c = getchar();
	while(isdigit(c))x = x * 10 + c - '0',c = getchar();
	return x;
}
queue<ll> Q[4];
int val[maxn],n,m,q,u,v,t;
ll delta;
inline int findmax(){
	int res = 0;
	for(int i = 1;i <= 3;i++)
		if(!Q[i].empty() && (!res || Q[i].front() > Q[res].front()))res = i;
	return res;
}
inline ll cut(ll x){return 1ll * u * x / v;}
inline void solve(int tim){
	ll x = Q[findmax()].front();Q[findmax()].pop();
	if(tim % t == 0)printf("%lld ",x + delta);
	Q[2].push(cut(x + delta) - delta - q);Q[3].push(x - cut(x + delta) - q);
	delta += q;
}
int main(){
	n = read(),m = read(),q = read(),u = read(),v = read(),t = read();
	for(int i = 1;i <= n;i++)val[i] = read();
	sort(val + 1,val + 1 + n);
	for(int i = n;i >= 1;i--)Q[1].push(val[i]);
	for(int i = 1;i <= m;i++)solve(i);
	putchar('\n');
	for(int i = 1;i * t <= n + m;i++){
		for(int j = 1;j <= t - 1;j++)
			Q[findmax()].pop();
		printf("%lld ",Q[findmax()].front() + delta);
		Q[findmax()].pop();
	}
	putchar('\n');
	return 0;
}

4、列队

算法思路:暴力先拿前六组得分 线段树、平衡树、树状数组----啥都不会
估分:30;
实得:30;
我的暴力代码:

#include<bits/stdc++.h>
using namespace std;
int n,m,p,x[10001],y[10001],a[10010][10010],t;
int main(){
	cin>>n>>m>>p;
	for(int i=1;i<=p;i++)
	    cin>>x[i]>>y[i];
	for(int i=1;i<=n;i++)
	    for(int j=1;j<=m;j++)
	        a[i][j]=(i-1)*m+j;
	for(int i=1;i<=p;i++){
		cout<<a[x[i]][y[i]]<<endl;
		t=a[x[i]][y[i]];
		for(int j=y[i];j<m;j++)a[x[i]][j]=a[x[i]][j+1];
		for(int j=x[i];j<n;j++)a[j][m]=a[j+1][m];
		a[n][m]=t;
	}
	return 0;
}

正解(洛谷):

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n,m,q,x,y,pos,tot,lim,rt[300005],ls[12000005],rs[12000005],sm[12000005];vector<ll>v[300005];
int que(int x,int l,int r,int v)
{
	if(l==r) return l;
	int mid=(l+r)>>1,tmp=mid-l+1-sm[ls[x]];
	if(v<=tmp) return que(ls[x],l,mid,v);
	return que(rs[x],mid+1,r,v-tmp);
}
void upd(int &x,int l,int r,int p)
{
	if(!x) x=++tot;sm[x]++;
	if(l==r) return;int mid=(l+r)>>1;
	if(p<=mid) upd(ls[x],l,mid,p);
	else upd(rs[x],mid+1,r,p);
}
ll wk1(int x,ll y)
{
	pos=que(rt[n+1],1,lim,x);upd(rt[n+1],1,lim,pos);
	ll ans=pos<=n?1ll*pos*m:v[n+1][pos-n-1];
	return v[n+1].push_back(y?y:ans),ans;
}
ll wk2(int x,int y)
{
	pos=que(rt[x],1,lim,y);upd(rt[x],1,lim,pos);
	ll ans=pos<m?1ll*(x-1)*m+pos:v[x][pos-m];
	return v[x].push_back(wk1(x,ans)),ans;
}
int main()
{
	scanf("%d%d%d",&n,&m,&q);lim=max(n,m)+q;
	for(;q--;printf("%lld\n",y==m?wk1(x,0):wk2(x,y))) scanf("%d%d",&x,&y);
}

反思

知识点上有好多好多盲区以及不熟练的地方,还得多加学习、练习

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

熙筠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值