2019HDU多校第一场

D Vacation

题意;

给出 n + 1 n+1 n+1 辆车的车长 l i l_i li、车头到终点的距离 s i s_i si、速度 v i v_i vi,问离第一辆车到终点的时间是多少。

如果有前车速度慢的情况,那么肯定是按照前车的速度行驶,枚举前车速度即可。

AC代码:
const int N = 5e5 + 50;
int s[N], v[N], l[N];
double ans;
int main()
{
	int n;
	while (~sd(n))
	{
		rep(i, 0, n)
			sd(l[i]);
		rep(i, 0, n)
			sd(s[i]);
		rep(i, 0, n)
			sd(v[i]);
		ans = s[0] * 1.0 / v[0];
		int sum = 0;
		rep(i, 1, n)
		{
			sum += l[i];
			ans = max((sum + s[i]) * 1.0 / v[i], ans);
		}
		printf("%.10f\n", ans);
	}
	return 0;
}

I String

题意:

给你一个串,现需要你给出一个子序列,满足 26 26 26 个约束条件, l e n ( a i ) > = L i len(a_i)>=L_i len(ai)>=Li l e n ( a ) < = R i len(a)<=R_i len(a)<=Ri a i a_i ai 为从 a a a z z z 26 26 26 个字母。

约束条件为每次字母的出现次数的限制。

26 26 26 个队列把每个字符出现的位置一一存起来,要求的字符串是字典序最小的 所以需要从 a a a 开始枚举到 z z z

字符串的长度是 k k k ,对于每一个位置来说, a − z a-z az 都有可能,所以枚举每个位置,对于每个位置枚举 26 26 26 个字母,如果可以放进答案数组就放,放不下就 b r e a k break break

AC代码:
const int N = 1e5 + 50;

char s[N];
int k, len, cl, flag;
int l[30], r[30];
int cnt[N][30];
int num[30];
int ans[N];
int main()
{
	while (~ss(s + 1))
	{
		sd(k);
		rep(i, 0, 25)
		{
			sdd(l[i], r[i]);
			num[i] = 0;
		}
		queue<int> q[30];
		len = strlen(s + 1);
		rep(i, 1, len)
		{
			q[s[i] - 'a'].push(i);
		}
		rep(i, 0, 25)
			cnt[len + 1][i] = 0;
		per(i, len, 1)
		{ //cnt[i][j]记录的是i位置之后j字符的数量,后缀
			rep(j, 0, 25)
			{
				if (s[i] == 'a' + j)
					cnt[i][j] = cnt[i + 1][j] + 1;
				else
					cnt[i][j] = cnt[i + 1][j];
			}
		}
		cl = 0; //已经放好的字母的位置
		rep(pos, 1, k)
		{
			flag = 0;
			rep(i, 0, 25)
			{
				if (num[i] >= r[i])
					continue;
				while (!q[i].empty() && q[i].front() <= cl)
					q[i].pop();
				if (!q[i].empty())
				{
					int ok = 1;
					num[i]++;
					rep(j, 0, 25)
					{ //判断用上当前位置字符i之后,剩下的字符是否满足最低限制
						if (cnt[q[i].front() + 1][j] + num[j] < l[j])
						{
							ok = 0;
							break;
						}
					}
					if (ok)
					{ //满足最低限制之后,判断  如果只用上最低数量的字符是否比k大,
						//如果都用上最大数量的字符是否比k小
						int lit1 = 0, lit2 = 0;
						rep(j, 0, 25)
							lit1 += max(l[j] - num[j], 0);
						rep(j, 0, 25)
							lit2 += min(r[j] - num[j], cnt[q[i].front() + 1][j]);
						if (lit1 > k - pos || lit2 < k - pos)
							ok = 0;
					}
					if (!ok)
					{ //如果不满足,那么这个位置的字符i不能当做答案
						num[i]--;
					}
					else
					{ //如果能,则更新cl,记录答案,pos位置满足,flag=1;
						cl = q[i].front();
						ans[pos] = i;
						flag = 1;
						break;
					}
				}
			}
			if (!flag)
				break; //如果a-z都不能放入答案那么结束循环,输出-1;
		}
		if (flag)
		{
			for (int i = 1; i <= k; i++)
				printf("%c", ans[i] + 'a');
			printf("\n");
		}
		else
			printf("-1\n");
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值