A. Max Plus Size
当字符串长度为偶数是,size=n/2,
长度为奇数时,分类讨论最大值在奇数位还是偶数位,判断时加入i%2和d%2
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define all(a) a.begin(),a.end()
void solve(){
ll n,m=0,d=0;
cin>>n;
vector<ll> p(n+1);
for(ll i=1;i<=n;i++){
cin>>p[i];
if(m<=p[i]){
if(n%2){
if((p[i]+i%2)>(m+d%2)){
m=p[i];
d=i;
}
}
else {
m=p[i];
d=i;
}
}
}
if(n%2&&d%2)cout<<m+n/2+1<<'\n';
else cout<<m+n/2<<'\n';
}
int main(){
#ifdef Online_Judge
freopen("INPUT.in","r",stdin);
freopen("OUTPUT.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t = 1;
cin>>t;
while(t--)
solve();
return 0;
}
B. All Pairs Segments
可以直接计算覆盖线段数(见代码),O(n)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define all(a) a.begin(),a.end()
void solve(){
ll n,Q,tim=0;
cin>>n>>Q;
vector<ll> p(n+1),q(Q);
map<ll,ll> cnt;
for(ll i=1;i<=n;i++)cin>>p[i];
for(ll i=0;i<Q;i++)cin>>q[i];
sort(p.begin(),p.end());
if(n==2){
cnt[1]=p[n]-p[n-1]+1;
}
else{
for(ll i=2;i<n;i++){
tim=(i-1)*(n-i+1)+n-i;
cnt[tim]++;
tim=i*(n-i);
cnt[tim]+=p[i+1]-p[i]-1;
}
cnt[n-1]+=p[2]-p[1]+1;
}
for(auto i:q){
cout<<cnt[i]<<' ';
}
cout<<'\n';
}
int main(){
#ifdef Online_Judge
freopen("INPUT.in","r",stdin);
freopen("OUTPUT.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t = 1;
cin>>t;
while(t--)
solve();
return 0;
}
C. Cards Partition
鸽巢原理。子集大小为s(1<=s<=n),数量最多的牌a有x张,牌的总数为sum(也就是pre[n]),满足(sum+k)/s>=x(因为至少有x个子集可以分配x个a),并且需要整除,即[sum,sum+k]上存在一个数是s的倍数。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define all(a) a.begin(),a.end()
void solve(){
ll n,k;
cin>>n>>k;
vector<ll> p(n+1),pre(n+1);
for(ll i=1;i<=n;i++){
cin>>p[i];
}sort(p.begin(),p.end());
for(ll i=1;i<=n;i++){
pre[i]=pre[i-1]+p[i];
}
ll s=n;
for(;s>=1;s--){
if(p[n]*s<=pre[n]+k){
if((pre[n]+k)%s<=k)
{
cout<<s<<'\n';
return ;
}
}
}
cout<<1<<'\n';
}
int main(){
#ifdef Online_Judge
freopen("INPUT.in","r",stdin);
freopen("OUTPUT.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t = 1;
cin>>t;
while(t--)
solve();
return 0;
}
D. Speedbreaker
时间为t的城市,出现在[l,r],如果r-l+1>t,就说明无法全部占领,若可以,开始的点可能在[r-t+1,l+t-1],t从最小的开始遍历,同时更新l和r。统计被所有情况覆盖的城市数量,用差分。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define all(a) a.begin(),a.end()
void solve(){
ll n,ans=0,x;
cin>>n;
vector<ll> a(n+1),b(n+1,n+1),diff(n+2);
vector<ll> p(n+1),cnt(n+1);
for(ll i=1;i<=n;i++){
cin>>x;
p[i]=x;
cnt[x]++;
a[x]=max(a[x],i);
b[x]=min(b[x],i);
}
if(p[1]<n&&p[n]<n){
cout<<"0\n";
return ;
}
ll s=1;
ll l=n,r=1;
sort(p.begin(),p.end());
for(ll i=1;i<=n;i+=cnt[p[i]]){
l=min(l,b[p[i]]);
r=max(r,a[p[i]]);
if(p[i]<r-l+1){
cout<<"0\n";
return ;
}
else{
ll nl=max(r-p[i]+1,s);
ll nr=min(l+p[i]-1,n);
diff[nl]+=cnt[p[i]];diff[nr+1]-=cnt[p[i]];
}
}
for(ll i=1;i<=n;i++){
diff[i]+=diff[i-1];
ans+=(diff[i]==n);
}cout<<ans<<'\n';
}
int main(){
#ifdef Online_Judge
freopen("INPUT.in","r",stdin);
freopen("OUTPUT.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t = 1;
cin>>t;
while(t--)
solve();
return 0;
}