A.Crossmarket
一个人得全走,另一个人可以用一步横跨一行或者一列,即:
answer : (n−1)+(m−1)+1+(min(n,m)−1)=min(n,m)+n+m−2.
特判:(n,m)=(1,1) answer is 0
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N =3e5+10,mod=998244353;
signed main()
{
int T;
cin>>T;
while(T--)
{
int m,n;
cin>>n>>m;
if(m==n&&m==1)
{
cout<<0<<endl;
continue;
}
cout<<(m+n-2)+min(m,n)<<endl;
}
return 0;
}
B.1715B - Beautiful Array
the existence of the answer: k⋅b ≤ s ≤ k⋅b+(k−1)⋅n
意思就是s起码要为k*b,不然漂亮值凑不到b。上限是不能超过k⋅b+(k−1)⋅n,就是其余位是k-1,最大的那一位是k*b+k-1(减一是保证除k后向下取整的结果不是k+1,是k)
然后就输出就行,符合条件即可,顺序不重要
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N =3e5+10,mod=998244353;
signed main()
{
int t;
cin>>t;
while(t--)
{
int n,k,b,s;
cin>>n>>k>>b>>s;
if(s<k*b||k*b+(k-1)*n<s)
{
cout<<-1<<endl;
continue;
}
int out=k*b;
s-=out;
for(int i=1;i<n;i++)
{
if(s>=k-1)
cout<<k-1<<" ",s-=k-1;
else if(s<k-1&&s>0)
cout<<s<<" ",s=0;
else
cout<<0<<" ";
}
cout<<out+s<<endl;
}
return 0;
}
C.1715C - Monoblock
先提一下题解里的式子:ans += (a[i] != a[i + 1]) * (n - (i + 1) + 1) * i;
//我一下看不透,但大概意思应该差不多,我的思路是这样的:
考虑每一位数字的贡献就行,对于包含这个数字的区间,与前一个数字重复、不重复的两种情况有不同的贡献;
如果与前一个数字不同,那贡献就是 i*(n-i+1);
否则贡献就是n-i+1(和另一种情况的差距就是不包含上一个数字的区间);
ans初始化为n,默认第一个数字对包含它的n个区间都有1的贡献。
然后在m次改数据的时候,先减去原本的数对左右的影响,改变后再加上对左右的影响即可。
写一组数据看看:1 2 2 4 5
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N =3e5+10,mod=998244353;
signed main()
{
int n, m;
cin >> n >> m;
vector<int> a(n + 2, 0);
for (int i = 1; i <= n; ++i)
{
cin >> a[i];
}
int ans = n;
for(int i=2;i<=n;i++)
{
if(a[i]!=a[i-1])
ans+=i*(n-i+1);
else
ans+=n-i+1;
}
//cout<<"ans="<<ans<<endl;
while(m--)
{
int index,x;
cin>>index>>x;
//先减去原来的
if(a[index]!=a[index-1])
ans-=index*(n-index+1);
else
ans-=n-index+1;
if(a[index+1]!=a[index])
ans-=(index+1)*(n-(index+1)+1);
else
ans-=n-(index+1)+1;
//改变后加上新的
a[index]=x;
if(a[index]!=a[index-1])
ans+=index*(n-index+1);
else
ans+=n-index+1;
if(a[index+1]!=a[index])
ans+=(index+1)*(n-(index+1)+1);
else
ans+=n-(index+1)+1;
cout<<ans<<endl;
}
return 0;
}