1. 程式人生 > 其它 >CF1467B Hills And Valleys 題解

CF1467B Hills And Valleys 題解

技術標籤:題解演算法c++

題目傳送門
解題思路:
題目中說只能修改一個數字的值,那麼顯然我們就可以列舉每個 i ( 2 ≤ i ≤ n ) i\ \left(2\le i \le n\right) i(2in) ,那麼我們修改第 i i i 個數字的話,顯然我們修改之後只有 i − 1 , i , i + 1 i-1,i,i+1 i1,i,i+1 三個位置的狀態發生了改變,我們只要預處理不修改的答案總和就可以了。
修改的時候我們會發現,要想讓修改之後的答案最小,我們就需要將這個數字的值修改成前一個數的值或者後一個數字的值,也可能是兩者的平均數。
最後記得注意修改第 1 1

1 個和修改第 n n n 個的情況,因為這個我WA了3發
Tips:記得多組資料清空陣列。
程式碼:

#include<cstdio>
#include<cstring>
#define maxn 300039
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
//#define debug
typedef int Type;
inline Type read(){
	Type sum=0;
	int flag=0;
	char c=getchar();
	while((c<'0'||c>'9')&&
c!='-') c=getchar(); if(c=='-') c=getchar(),flag=1; while('0'<=c&&c<='9'){ sum=(sum<<1)+(sum<<3)+(c^48); c=getchar(); } if(flag) return -sum; return sum; } int T; int n,a[maxn]; int cheg(int x){ if(x==1||x==n) return 0; return (a[(x)]<a[(x+1)]&&a[(x)]<
a[(x-1)]); } int ches(int x){ if(x==1||x==n) return 0; return (a[(x)]>a[(x+1)]&&a[(x)]>a[(x-1)]); } void work(){ memset(a,0,sizeof(a)); n=read(); for(int i=1;i<=n;i++) a[i]=read(); int sum,ans; sum=0; for(int i=2;i<n;i++){ if(cheg(i)) sum++; if(ches(i)) sum++; } ans=sum; int tmp,pre,end; for(int i=2;i<n;i++){ tmp=a[i]; pre=cheg(i)+cheg(i-1)+cheg(i+1)+ches(i)+ches(i-1)+ches(i+1); a[i]=a[i-1]; end=cheg(i)+cheg(i-1)+cheg(i+1)+ches(i)+ches(i-1)+ches(i+1); ans=min(ans,sum-pre+end); a[i]=a[i+1]; end=cheg(i)+cheg(i-1)+cheg(i+1)+ches(i)+ches(i-1)+ches(i+1); ans=min(ans,sum-pre+end); a[i]=(a[i+1]+a[i-1])>>1; end=cheg(i)+cheg(i-1)+cheg(i+1)+ches(i)+ches(i-1)+ches(i+1); ans=min(ans,sum-pre+end); a[i]=tmp; } pre=cheg(2)+ches(2); a[1]=a[2]; end=cheg(2)+ches(2); ans=min(ans,sum-pre+end); pre=cheg(n-1)+ches(n-1); a[n]=a[n-1]; end=cheg(n-1)+ches(n-1); ans=min(ans,sum-pre+end); printf("%d\n",ans); return; } int main(){ T=read(); while(T--) work(); return 0; }