原题链接:http://codeforces.com/contest/1197/problem/A
题意: 定义 k 阶梯子,两边各一块木板长度至少 k+1,即必须要比台阶数大,中间 k 块木板长度至少为1 。问给你 n 块木板,最多能搭成几阶的梯子。
思路:
Code(C++):
#include
#include
using namespace std;
int a[100010];
int main(){
int t; cin>>t;
while(t--){
int n; cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
sort(a,a+n);
if(n<=2)
cout<<0<<endl;
else{
if(n-2>=a[n-2]) //台阶数必须要小于第二大根柱子的长度
cout<<a[n-2]-1<<endl;
else
cout<<n-2<<endl;
}
}
return 0;
}
原题链接:http://codeforces.com/contest/1197/problem/B
题意: n个柱子上各有一个圆盘, 可以在满足以下条件基础上无限次移动圆盘:
问是否能够把所有圆盘都移动到一个柱子上?
思路: 先找到所有柱子中圆盘半径最大的那根,然后判断其左边是不是从左到右递增,其右边是不是从右到左递增,若是,则输出“YES”,否则输出“NO”。
Code(C++):
#include
using namespace std;
int a[200010];
int main(){
int n; cin>>n;
int maxn=-1,pos;
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]>maxn){
pos=i;
maxn=a[i];
}
}
for(int i=1;i<pos-1;i++){
if(a[i]>a[i+1]){
cout<<"NO"<<endl;
return 0;
}
}
for(int i=pos+1;i<n;i++){
if(a[i]<a[i+1]){
cout<<"NO"<<endl;
return 0;
}
}
cout<<"YES"<<endl;
return 0;
}
原题链接: http://codeforces.com/contest/1197/problem/C
题意: 给你长度为n的非递减数组,你需要切为k个连续的子序列数组,每个数组的切分代价是max(a[i])-min(a[j]),现在问你总代价最小是多少?
思路: 先算出所有相邻两数间的差值,共 n-1 个差值。每段子序列的切分代价其实就是该子序列中的所有相邻两数的差值之和,而分成 k 段连续子序列数组也就少了 k 个差值,那么只需要把所有相邻两数间的差值从小到大排序,前 n-k 段差值之和即为最小的切分代价。
Code(C++):
#include
#include
using namespace std;
int a[300010],b[300010];
int main(){
int n,k;
cin>>n>>k;
cin>>a[0];
for(int i=1;i<n;i++){
cin>>a[i];
b[i]=a[i]-a[i-1];
}
sort(b+1,b+n);
long long ans=0;
for(int i=1;i<=n-k;i++)
ans+=b[i];
cout<<ans<<endl;
}
原题链接: http://codeforces.com/contest/1197/problem/D
题意: 给你一个序列,求一个子序列 a[l]~a[r] 能使得该子序列的 sum(l,r)-k*(r-l+1)/m(向上取整)的值是在所有子序列中的最大值并输出该值。特别地,一个长度为0的子序列的答案为0。
思路: 由表达式可知每隔 m 个数就得减掉 k ,所以枚举每一个区间的起点,对原数组进行处理,每隔 m 个数就减掉 k ,然后再确定最大区间和,如果区间和小于0就更新为0。
Code(C++):
#include
using namespace std;
const int N=3e5+10;
int a[N],b[N];
int main(){
int n,m,k;
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
cin>>a[i];
long long ans=0;
for(int j=0;j<m;j++){ //枚举每一个区间的起点
for(int i=1;i<=n;i++){
b[i]=a[i];
if(i%m==j)
b[i]-=k;
}
long long sum=0;
for(int i=1;i<=n;i++){
sum+=b[i];
if(i%m==j)
ans=max(ans,sum);
sum=max(sum,0ll); //如果区间都是负数则更新为0
}
}
cout<<ans<<endl;
return 0;
}