先是题解
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;
}