目录
C. Qpwoeirut And The City
D1. Chopping Carrots (Easy Version)
链接:题目链接
题意:给一个长度为n的数组,一个点同时大于左边和右边,该点为凉爽点(第一和最后不会是),求凉爽点最多时,添加高度最少是多少。
input
6 3 2 1 2 5 1 2 1 4 3 6 3 1 4 5 5 2 8 4 2 1 3 5 3 6 1 6 1 10 1 1 10 1 8 1 10 11 1 10 11 10 1output
2 0 3 3 0 4
思路:
当长度为奇数时
比如第一个样例,下标i为1-n,那么下标为偶数的点必需是凉爽点,这是直接加起来就行
sum+=max(0LL,max(a[i-1],a[i+1])+1-a[i]);
当长度为偶数时
可以发现第2,3个,第4,5个,第6,7个.....中选一个作为凉爽点,而且不能有相邻
如果第3个为凉爽点,那么后面的就一定是5,7,9...
如果第5个为凉爽点,那么后面的就一定是7,9,11...
也就是从某一处开始选的是右边奇数的,那么后面一定都是选右边奇数,而前边一定都是选左边偶数的
那么记录选左边的从前到后的和x[i],以及选右边的从后到前的和y[i]
答案就是max(x[i]+y[i+1])
fo(1,n){
if(i%2==0) x[i/2]+=x[i/2-1]+max(0LL,max(a[i-1],a[i+1])+1-a[i]); //从前往后
}
for(int i=n-1;i>=3;i-=2){
y[i/2]+=y[i/2+1]+max(0LL,max(a[i-1],a[i+1])+1-a[i]); //从后往前
}
int maxx=1e18;
for(int i=0;i
代码:
#include
using namespace std;
#define fo(a,b) for(int i=a;i<=b;i++)
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
#define ll long long
#define int long long
#define endl '\n'
#define dou double
const ll mod=1e9+7;
#define M 1000005
int T,n;
int a[M],x[M],y[M];
signed main(){
cin.tie(nullptr)->sync_with_stdio(false);
cin>>T;
while(T--){
cin>>n;
int res=n/2-1;
fo(0,n+1) x[i]=y[i]=0;
fo(1,n) cin>>a[i];
fo(1,n){
if(i%2==0) x[i/2]+=x[i/2-1]+max(0LL,max(a[i-1],a[i+1])+1-a[i]); //从前往后
}
for(int i=n-1;i>=3;i-=2){
y[i/2]+=y[i/2+1]+max(0LL,max(a[i-1],a[i+1])+1-a[i]); //从后往前
}
if(n%2) cout<
链接:题目链接
题意:给一个数组,需要除一次1~k中的数,然后结果最小和最大的差别最小为多少
input
7 5 2 4 5 6 8 11 5 12 4 5 6 8 11 3 1 2 9 15 7 3 2 3 5 5 6 9 10 6 56 54 286 527 1436 2450 2681 3 95 16 340 2241 2 2 1 3output
2 0 13 1 4 7 0
思路:
这个代码是二分做的,先枚举答案,比如问差值为5可以吗,再枚举左端点l(1-3e3),那么右端点就是l+5,遍历数组判断是否都在这个l到r之间,时间复杂度O(n*n*logn)
判断能不能在l到r之间,是让除数为min(k,(a[i]-1)/r+1),保证a[i]除以该数一定是刚好小于等于r的,但是有细节问题,再判断一次min(k,(a[i]-1)/r+1)-1,代码不是有点乱了
类似思路还可以O(n*n)处理以(1-3e3)为右端点,左边最大为多少,更新答案即可,应该也是可以的
代码:
#include
using namespace std;
#define fo(a,b) for(int i=a;i<=b;i++)
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
#define ll long long
#define endl '\n'
#define dou double
const ll mod=1e9+7;
#define M 1000005
int T,n,k;
int a[M];
int solve(int l,int r){ //判断区间l-r可不可以
fo(1,n){
if(l==0){
if(a[i]/kr) return 0;
}
else if(a[i]r)){
if(res==1||(a[i]/(res-1)r))
return 0;
}
}
}
return 1;
}
int check(int d){ //判断差值为d可不可以
for(int i=0;i<=3e3;i++){
if(solve(i,i+d)) return 1;
}
return 0;
}
signed main(){
cin>>T;
while(T--){
cin>>n>>k;
fo(1,n) cin>>a[i];
int l=0,r=1e4,ans=0;
while(l<=r){
int mid=(l+r)/2;
if(check(mid)){
r=mid-1;
ans=mid;
}else{
l=mid+1;
}
}
cout<