[Educational Codeforces Round 176 (Rated for Div. 2)](https://codeforces.com/contest/2075) (AB,补C)
Educational Codeforces Round 176 (Rated for Div. 2) (AB,补C)
A
idea:(因为没注意到k只能为奇数的惨案qaq)
因为奇-奇=偶,偶-偶=偶
所以只需要判断n的奇偶然后先进行一次操作即可
#include<bits/stdc++.h>
#define N 1005
#define mod 998244353
using namespace std;
typedef long long ll;
void solve()
{
int n,k;
cin>>n>>k;
ll ans = 0;
if(n&1==1)
{
n-=k;
ans++;
}
k--;
ans += (n+k-1)/k;
cout<<ans<<"\n";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int T = 1;
cin>>T;
while(T--)
solve();
return 0;
}
B:
注意到当k>=2的时候,任何情况下都能选前k+1个最大的(手上操作一下即可)
所以只需要特判k==1的情况(要不是被A卡了半年,一把就绿了,唉唉,这B能评1400有点虚高了)
#include<bits/stdc++.h>
#define N 1005
#define mod 998244353
using namespace std;
#define int long long
typedef long long ll;
void solve()
{
int n,k;
cin>>n>>k;
ll ans = 0;
vector<int>a(n+1);
for(int i = 1;i <= n;i++)
{
cin>>a[i];
}
if(k==1)
{
for(int i = 2;i < n;i++)
{
ans = max(ans,a[i]+max(a[1],a[n]));
}
ans = max(ans,a[1]+a[n]);
}
else
{
ans = 0;
sort(a.begin()+1,a.end(),greater<int>());
for(int i = 1;i <= k+1;i++)
{
ans+=a[i];
}
}
cout<<ans<<"\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int T = 1;
cin>>T;
while(T--)
solve();
return 0;
}
C:先补一下前缀预处理的写法
idea1:假设现在两种颜色,第一种选i,则第二种选n-i个,那么对每一种都这么考虑必定tle,
现在进行这样一种操作,将每个>=a[i]的用数组Num存储进行后缀和,表示现在有多少数量大于等于i的木板,当选a[i]块木板满足时,那么少选这块木板也能满足条件,e.g:对第三个样例
12 3
5 9 8
当选 i = 4;n - i = 8的时候,如果不选a[1],那么因为≥8的有8和9,所以选2:3也可以,只要a[n-i]>0
再进一步考虑,将区间划分为[i,n-i+1]和[n-i,n](因为(3,9)和(9,3)是两种选法),但只需要考虑[i,n-i-1]即可,最终将ans*2就可以解决重复计算的问题。
那么如何计算?
对于这一组样例,如果选4:8个,那么能选4的为c(1,3),能选8的为c(1,2);
假设第一种选x个,那么x = num[i] - num[n-i];(表示有多少个木板数量>=i的)
第二种则设为y = num[n-i],最终答案为ans += x×y + y×(y-1),//后面的是表示从>=i的木板中任选两块
如果i == n-i时,会出现重复,ans += x×y + y×(y-1)/2;
#include<bits/stdc++.h>
#define mod 998244353
using namespace std;
typedef long long ll;
#define int unsigned long long
int num[200005];
int N = 0;
void solve()
{
int n,m;
cin>>n>>m;
int h = max(n,m);//T范围较大,防爆
for(int i = 1;i <= h;i++) num[i] = 0;//别用memset
vector<int>a(m+1);
for(int i = 1;i <= m;i++)
{
cin>>a[i];
num[a[i]]++;
}
for(int i = n-1;i >= 1;i--)
{
num[i] += num[i+1];//预处理后缀和
}
int ans = 0;
//1 : n-i 选i个,另一个选n-i个, ans += x*y+y*(y-1);
//i==n-i /2
for(int i = 1;i <= n-i; i++)
{
int x = num[i] - num[n-i],y = num[n-i];
if(i != n - i) ans += x*y + y*(y-1);
else ans += x*y + y*(y-1)/2;
}
cout<<ans*2<<"\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int T = 1;
cin>>T;
while(T--)
solve();
return 0;
}
二分写法:找到满足的区间然后统计即可
#include<bits/stdc++.h>
#define mod 998244353
using namespace std;
typedef long long ll;
#define int long long
int num[200005];
int N = 0;
void solve()
{
int n,m;
cin>>n>>m;
vector<int>a(m);
for(int i = 0;i < m;i++) cin>>a[i];
sort(a.begin(),a.end());
int j = 1;
ll ans = 0;
for(int i = 1;i <= n/2;i++)
{
j = n-i;
int x = lower_bound(a.begin(),a.end(),i)-a.begin();
int y = lower_bound(a.begin(),a.end(),j)-a.begin();
if(y == m) continue;
if(i == j)
{
ans += (m-x-1)*(m-y)/2;
}
else
{
ans += (m-x-1)*(m-y);
}
}
cout<<ans*2<<"\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int T = 1;
cin>>T;
while(T--)
solve();
return 0;
}

浙公网安备 33010602011771号