ARC072简要题解

在这里插入图片描述

先是题解

C题:
如果上一个sum正,这个sum该是负,但是他正了,那么改到-1肯定最优。
反过来,改到1肯定最优。
第一个sum可正可负,那么不妨两个都试试。
wa是因为自己ZZ掉了,只判了为0的情况,然后交了之后光速叉掉改回来

#include<bits/stdc++.h>
using namespace std;
int a[100010], n;
long long sum = 0;
long long ans = 0;

long long solve(bool k) { 
	sum = ans = 0;
	int type = k;
	for(int i=1;i<=n;++i) { 
		//1 = fu
		long long ts = sum + a[i];
		if(type == 1 && ts >= 0) 
			ans += (ts + 1), ts = -1;
		if(type == 0 && ts <= 0) 
			ans += (1 - ts), ts = 1;
		sum = ts, type ^= 1;
	} 
	return ans;
} 

int main() { 
	scanf("%d",&n);
	for(int i=1;i<=n;++i) 
		scanf("%d",&a[i]);
	long long ans = 1000000000000000000;
	ans = min(ans, solve(1));
	ans = min(ans, solve(0));
	cout<<ans;
	return 0;
} 

D:
打了个表发觉好像差不超过1就是Brown赢(HHHHHHH
注意不要把Brown打成Brorn
WSSB

#include<bits/stdc++.h>
using namespace std;
long long a,b;
int main() { 
	cin>>a>>b;
	printf(abs(a-b)<=1 ? "Brown" : "Alice");
	return 0;
} 

E:
拿到题第一时间一脸懵。
冷静了一下发觉那个修改就是任选一个比当前dist小的dist,然后想到数据结构题里面经典的 “不能被表示的最小的数字”
自然想到,顺着处理一个前缀,pre[i]表示一路顺着过来到i,此时离终点的dist
反着处理一个后缀,suf[i]表示i这个后缀顺着下去,可以处理的一段连续到1的长度的最大值(好像有点绕,上面那个东西是suf[i]+1
之前数据结构那个模型,是val <= sum + 1就可以往上拼,这个因为允许走到数字背后去,所以val <= 2*sum + 1就可以了。
拿到这个结论,一顿操作下去就好了。
前两遍人比较ZZ,拿了个优先队列,做数据结构那个模型去了qwq
然后发觉好像不太能任选顺序,改了改就过去了

#include<bits/stdc++.h>
using namespace std;
long long n, m, T;
long long pre[500010];
long long suf[500010];
long long a[500010];

int main() { 
	scanf("%lld%lld",&n,&T);
	for(int i=1;i<=n;++i) 
		scanf("%lld",&a[i]);
	pre[0] = T;
	for(int i=1;i<=n;++i) { 
		long long nval = pre[i-1] - a[i];
		if(nval < 0) 
			nval = -nval;
		pre[i] = min(pre[i-1], nval);
	} 
	for(int i=n;i>=1;--i) { 
		suf[i] = suf[i+1];
		long long nw = a[i];
		if(nw > suf[i]*2 + 1) 
			continue;
		suf[i] = nw + suf[i];
	} 
//	for(int i=1;i<=n;++i) 
//		printf("%lld  ",pre[i]);
//	printf("\n");
//	for(int i=1;i<=n;++i)
//		printf("%lld  ",suf[i]);
//	printf("\n");

	int m, q;
	scanf("%d",&m);
	for(int i=1;i<=m;++i) { 
		scanf("%d",&q);
		bool vis = pre[q-1] > suf[q+1];
		printf(!vis ? "NO\n" : "YES\n");
	} 
	return 0;
} 

F:
一脸不会,赛后膜了发题解。
我们用(V,T)来定义一坨水。
试图从第i-1天的满池最优状态得到第i天的满池最优状态
假设池子容量为30, 我们只关心Day3和Day4的事儿。
V[1] = 10, T[1] = 7
V[2] = 10, T[2] = 10
V[3] = 10, T[3] = 10
V[4] = 10, T[4] = 20
在考虑第三天的时候,你发觉你需要不放水,让所有的水都在池子里,才能满。
在考虑第四天的时候,你发现第一天的(10,7)让你亏了。
时光倒流一下,把这一坨水从池子里捞走,此时的操作科学合理。
换组数据。
V[1] = 10, T[1] = 7
V[2] = 10, T[2] = 10
V[3] = 10, T[3] = 1
V[4] = 10, T[4] = 20
在考虑第四天的时候,你发觉第三天的(10,1)让你亏惨了。
你试图时光倒流然后把这坨水抬走。
发觉不允许,因为后来的水会与比他先到的水产生混合。
但是,如果后来的水的温度比先来的高,那么我们假装他没有混合。在扔掉一坨水的时候,优先扔掉先来的就好。
具体的,搞个队列,维护一下水的长相。
每次往里塞一坨水(V,T),先从时间早的那一端一顿pop,直到能塞得下。
从时间晚的那一端,挨个检查队列里面的水,对于每一坨满足T > T’的(V’,T’),都把他俩合并,用来模拟 “后来的低温水与先来的高温水平均了温度,所以不支持撤销后来的低温水” 这样一个过程。
然后算一算就好。

#include<bits/stdc++.h>
using namespace std;
struct pac { 
	long long v;
	double t;
};

pac merge(pac a, pac b) { 
	return {a.v + b.v, (a.t*a.v + b.t*b.v) / (1.00 * (a.v + b.v))};
} 
pac sth[500010];
int l, r;
long long n, M;
long long v;
double t;
double tottemp = 0;
int main() { 
	l = 1, r = 0;
	scanf("%d%lld",&n,&M);
	for(int i=1;i<=n;++i) { 
		scanf("%lf%lld", &t, &v);
		long long mor = i == 1 ? 0 : v;
		while(l <= r && mor > 0) { 
			if(mor > sth[l].v) { 
				mor -= sth[l].v, tottemp -= sth[l].v * sth[l].t;
				l++;
			} 
			else { 
				sth[l].v -= mor;
				tottemp -= sth[l].t * mor;
				mor = 0;
			} 
		} 
		pac nw = {v, t};
		tottemp += nw.v * nw.t;
		while(l <= r && sth[r].t > nw.t) { 
			nw = merge(nw, sth[r]);
			r--;
		} 
		sth[++r] = nw;
		printf("%.10lf\n",tottemp / M);
	} 
	return 0;
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值