今天要打的,所以我不得不提前写好文章,然后今天要写的也是两道的,也不是很难,上水课的时候写的。
分析
:这题也是个思维题,挺显然的,就是我们考虑从前往后扫一遍,看子序列里面单调不递增或者单调不递减(当然不能同时看),因为绝对值吗,很显然,单调不递增和单调不递减不影响绝对值的差值求和,所以就统计一下长度就行了,不能写假,反正思维题对细节的要求还是很高的。
:这题还是思维题,我现在状态就是天天写思维题,然后思维还是依托答辩。。。这题就是删去一个数和增加一个数有要付出一定的代价,然后求把序列变成一个 ~ 的排列所需的最小代价是多少。很显然,序列里出现的重复的数我们必须删掉(这是无论如何都要做的事情),然后我们可以用统计一下现有的所有数分别是多少。排序之后我们可以考虑暴力枚举,但是我们之前先要算一个值就是当第一个数不是的时候我们直接把这个序列变成所要付出的代价是多少,然后再考虑枚举所有的已有数,对于每个,当我们要把序列变成 ~ 所需付出的代价,直到枚举到。然后取个最小值即可。
代码
:
#include <bits/stdc++.h>
#define ll long long
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
using namespace std;
const int N=3e5+10;
int n,a[N],t;
void solve(){
int ans=0;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
if(n==1){
cout<<1<<"\n";
return;
}
int ok=-1;
if(a[2]>a[1]) ok=0;
if(a[2]<a[1]) ok=1;
if(a[2]==a[1]) ans++;
for(int i=3;i<=n;i++){
if(a[i]==a[i-1]) ans++;
else if(ok==0){
if(a[i]>a[i-1]) ans++;
else if(a[i]<a[i-1]) ok=1;
}
else if(ok==1){
if(a[i]<a[i-1]) ans++;
else if(a[i]>a[i-1]) ok=0;
}
else if(ok==-1){
if(a[i]>a[i-1]) ok=0;
if(a[i]<a[i-1]) ok=1;
}
}
cout<<n-ans<<"\n";
}
int main(){
IOS;
cin>>t;
while(t--) solve();
return 0;
}
:
#include <bits/stdc++.h>
#define ll long long
#define x first
#define y second
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
using namespace std;
const int N=2e5+10;
int n,a[N],t;
ll c,d;
map<int,ll> mp;
vector<int> v;
void solve(){
cin>>n>>d>>c;//c删除d增加
mp.clear();
v.clear();
for(int i=1;i<=n;i++){
cin>>a[i];
mp[a[i]]++;
}
ll ans=0;
for(auto it:mp){
v.push_back(it.x);
ans+=(it.y-1ll)*d;
}
sort(v.begin(),v.end());
ll res=ans;
int len=v.size();
if(v[0]==1) ans+=(len-1)*d;
else ans+=len*d+c;
for(int i=0;i<v.size();i++){
ll temp=res;
if(v[i]==1) continue;
temp+=(len-i-1)*d+c*(v[i]-i-1);
ans=min(ans,temp);
}
cout<<ans<<"\n";
}
int main(){
IOS;
cin>>t;
while(t--) solve();
return 0;
}
今晚就算打的在垃圾也别要发癫,球球你了,宝~