洛谷1月月赛div2题解

A.P6013 压岁钱

退役了,真的退役了…三个月没怎么刷题, d i v 2 div2 div2的第一题就把我弄自闭了,写了半个小时,跑的还死慢。。不过我想只要是人都能看懂我这个代码,大体上就是硬核模拟。

#include <stdio.h>
#include <iostream>
#include <queue>
#define int long long int
#define N 1000001
using namespace std;
struct node//并没有什么卵用的结构体,事实上在后面的读入中只需要3个变量。 
{
	int id,val,to;//id:事件;val:得到或花掉的钱;to:仅事件3才有的参数[持续到第几天] 
}a[N];
struct lst//这个结构体处理专门一系列的事件三 
{
	int duration,v;//duration代表封印持续到第几天,v代表封印的钱 
	bool operator < (const lst &a)const
	{
		return a.duration<duration;//把持续时间从小到达排序 
	}
}tmp;
int n,s,ans,f;
priority_queue<lst> q;//优先队列 
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	register int i,j;
	cin>>n;
	for(i=1;i<=n;i++)//枚举事件i 
	{
		while(!q.empty())
		{
			if(q.top().duration==i)//判断某个事件3的持续时间是否已经到了i 
			{
				s=s+q.top().v;//把钱拿回来 
				q.pop();//踢掉 
			}
			else break;//如果不是就不管 
		}
		cin>>a[i].id;//输入事件类型 
		if(a[i].id!=3)//如果不是3 
		{
			cin>>a[i].val;
			if(a[i].id==1)
			{
				s+=a[i].val;//直接赚钱即可 
			}
			else//事件2 
			{
				s-=a[i].val;//花钱 
				if(s<0)//如果没有足够的钱 
				{
					s+=a[i].val;//再加回来 
					ans++;//不满意的次数+1 
				}
			}
		}
		else//事件3 
		{
			cin>>a[i].val>>a[i].to;
			s-=a[i].val;//减钱 
			tmp.duration=a[i].to; 
			tmp.v=a[i].val;
			q.push(tmp);//塞进队列 
		}
		//cout<<s<<endl<<endl;
	}
	cout<<ans<<endl;
	return 0;
}

B.P6014 [CSGRound3]斗牛

太菜了,还是问了KillerXu才会AC做法的。一开始写的80分做法也是硬核模拟,因为必定有 2 2 2张牌是不取的,所以枚举这 2 2 2张牌即可。很简单易懂,总体复杂度是 O ( N 2 ) O(N^2) O(N2)

#include <stdio.h>
#include <iostream>
#define int long long int
#define N 1000001
using namespace std;
int a[N],n,s,t,tmp;
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	register int i,j,k;
	cin>>n;
	for(i=1;i<=n;i++)
	{
		cin>>a[i];
		s+=a[i];
	}
	tmp=s;
	for(i=1;i<=n;i++)
	{
		for(j=i+1;j<=n;j++)
		{
			tmp=s;
			if(i==j) continue;
			tmp=tmp-a[i]-a[j];
			if(tmp%10==0)
			{
				if((a[i]+a[j])%10==0) cout<<10<<endl;
				else cout<<(a[i]+a[j])%10<<endl;
				return 0;
			}
		}
	}
	cout<<0<<endl;
	return 0;
}

然而 O ( N 2 ) O(N^2) O(N2)肯定是过不了此题的,对于 S u b t a s k # 3 Subtask\#3 Subtask#3我们发现对于每一张牌的数都是 1 − 10 1-10 110的范围内,所以就用桶的思想,枚举 1 − 10 1-10 110可能的数即可。读入 O ( N ) O(N) O(N),算法 O ( 1 ) O(1) O(1)

#include <stdio.h>
#include <iostream>
#define int long long int
#define N 11
using namespace std;
int a[N],n,s,t,tmp,f;
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	register int i,j,k;
	cin>>n;
	for(i=1;i<=n;i++)
	{
		int wei;
		cin>>wei;
		a[wei]++;
		s+=wei;
	}
	for(i=1;i<=10;i++)
	{
		if(a[i]>=2 && (s-i*2)%10==0)
		{
			t=(i*2)%10;
			f=1;
		}
	}
	for(i=1;i<=9;i++)
	{
		for(j=i+1;j<=10;j++)
		{
			if(a[i]>0 && a[j]>0 && (s-i-j)%10==0)
			{
				t=(i+j)%10;
				if(t==0)
					t=10;
				f=1;
			}
		}
	}
	if(f==0) cout<<0<<endl;
	else cout<<t<<endl;
	return 0;
}

C.P6015 [CSGRound3]游戏

自闭了,瞎几把搞的,类似于尺取法,水了37分。有时间会独立发布AC解法。

#include <stdio.h>
#include <iostream>
#define N 1000001
#define int long long int
using namespace std;
int a[N],sum[N],n,m,G,s;
bool vis[N];
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	register int i(0),j(0),k;
	cin>>n;
	for(i=1;i<=n;i++)
	{
		cin>>a[i];
		sum[i]=sum[i-1]+a[i];
	}cin>>m;
	for(i=1;i<=n;i++)
	{
		if(sum[i]>m) G=i;
	}
	for(i=1;i<=m;i++)
	{
		for(j=1;j<=G+1;j++)
		{
			if(sum[j]>i) break;
		}
		for(k=j;k<=n;k++)
		{
			if(sum[k]-sum[j-1]>i) break;
		}
		if(sum[j-1]>sum[k-1]-sum[j-1])
		{
			vis[i]=1;
			s++;
		}
	}
	cout<<s<<endl;
	for(i=1;i<=m;i++)
	{
		if(vis[i]) cout<<i<<' ';
	}
	cout<<endl;
	return 0;
}

D.P6016 [CSGRound3]出游

彻底自闭。这是一个数学问题,不会。不过3分是很好骗的:只需要把概率加起来再取模即可。

总结:

我菜死了,被全场吊打。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值