CF Round #852 (Div.2) 解题报告【A~D】
\(\text{By yeminghan}\)
Codeforces Round #852 (Div.2)
垃圾场上了大分
以后,#define ll long long
。
A. Yet Another Promotion
一共有两种买法:
-
使用优惠,显然用就要用最多次优惠而不浪费,剩下的买费用较小的一天的。最小花费为 \(\left\lfloor\dfrac{n}{m+1}\right\rfloor\cdot a\cdot m+(n\bmod(m+1))\cdot\min(a,b)\)。
-
不使用优惠。答案为 \(n\cdot b\)。
综上,最小费用为 \(\min\left(\left\lfloor\dfrac{n}{m+1}\right\rfloor\cdot a\cdot m+(n\bmod(m+1))\cdot\min(a,b),n\cdot b\right)\)。
ll a,b,x,y;
void Solve()
{
cin>>a>>b>>x>>y;
cout<<min(a*(x/(y+1))*y+min(a,b)*(x%(y+1)),b*x)<<endl;
}
B. Fedya and Array
妙妙题。完全可以只有一个极大值 \(x\)、一个极小值 \(y\)。
int x,y;
void Solve()
{
cin>>x>>y;
cout<<(x-y)*2<<endl;
for(int i=x;i>=y;i--)cout<<i<<" ";
for(int i=y+1;i<x;i++)cout<<i<<" ";
cout<<endl;
}
C. Dora and Search
双指针。初始时令 \(l=1,r=n\)。
如果现在 \(a_l\) 是最小值或最大值,那么即使删右边的数,\(a_l\) 还是最小(大)值,所以必须删 \(a_l\)。
\(r\) 同理。
最后如果 \(l<r\) 就有解。
理论上可以 \(O(n)\),因为我懒就用的 set
。
const int N=200005;
int n,a[N],l,r;
set<int>num;
void Solve()
{
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
num.clear();
for(int i=1;i<=n;i++)num.insert(i);
l=1,r=n;
while(l<r)
{
int mi=*num.begin(),ma=*num.rbegin();
if(a[l]==mi||a[l]==ma)num.erase(a[l++]);
else if(a[r]==mi||a[r]==ma)num.erase(a[r--]);
else {return cout<<l<<" "<<r<<endl,void();}
}
cout<<-1<<endl;
}
D. Moscow Gorillas
枚举 \(\operatorname{mex}\) 值,然后去统计每种 \(\operatorname{mex}\) 值的方案数。
(我不会讲,看代码吧)
const int N=200005;
int n,p,q,pp[N],pq[N],pl,pr,ql,qr;
ll ans;
void Solve()
{
cin>>n;
for(int i=1;i<=n;i++){cin>>p;pp[p]=i;}
for(int i=1;i<=n;i++){cin>>q;pq[q]=i;}
pl=pr=pp[1],ql=qr=pq[1];
ll mi=min(pp[1],pq[1]),ma=max(pp[1],pq[1]);
ans=(mi*(mi-1)+(ma-mi-1)*(ma-mi)+(n-ma+1)*(n-ma))>>1;
for(int i=1;i<n;i++)
{
ll mil=min(pl,ql),mar=max(pr,qr);
ll mal=min(pp[i+1],pq[i+1]),mir=max(pp[i+1],pq[i+1]);
if(mil<=mir&&mar>=mal)ans+=max(0ll,max((mil-mal),0ll)*(mir-mar));
else if(mil>mir)ans+=max(0ll,(mil-mir)*(n-mar+1));
else ans+=max(0ll,(mal-mar)*mil);
pl=min(pl,pp[i+1]),pr=max(pr,pp[i+1]);
ql=min(ql,pq[i+1]),qr=max(qr,pq[i+1]);
}
cout<<ans+1;
}