Into Blocks(CodeForces Round #584)(優雅的貪心)

Into Blocks(不帶修改的EasyEasy版本)

題意:給定一個序列,通過改變其中的數字使所有相同的數字在數組中都是相鄰的,改變數字的方式爲:將數組中某個數字全部修改爲另外一個數字。求最少需要改變的元素
思路

  1. 由於最終狀態肯定是“一塊一塊”的,每一塊中都是一樣的數字
  2. 因此考慮預處理每種數字最靠右的位置,然後從左到右掃描整個序列
  3. 掃描的過程中以出現的數字的最靠右的位置爲界限,並且每遇到一個新數字就更新界限
  4. 而當掃描到界限位置出,表明改變當前區域內的數字不會影響到後面的區域,因此找出當前區域內出現次數最多的數字,並且把其他數字都改爲當前數字即爲最優
  5. 妙啊!heyuhhh nb!

題面描述

#include "bits/stdc++.h"
#define hhh printf("hhh\n")
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
using namespace std;
typedef long long ll;
typedef pair<int,int> pr;
inline int read() {int x=0;char c=getchar();while(c<'0'||c>'9')c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return x;}
 
const int maxn = 2e5+10;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const double eps = 1e-7;
 
int n, q, ans;
int a[maxn], x[maxn], cnt[maxn];
inline void max(int &a, int b) { if(a<b) a=b; }
 
int main() {
    //ios::sync_with_stdio(false); cin.tie(0);
    n=read(), q=read();
	for(int i=1; i<=n; ++i) cnt[x[a[i]=read()]=i,a[i]]++;
	for(int i=1; i<=n; ++i) {
		int l=i, r=x[a[i]], m=cnt[a[i]];
		while(i<r) ++i, max(r,x[a[i]]), max(m,cnt[a[i]]);
		ans+=r-l+1-m;
	}
	cout<<ans<<endl;
}

壓行過猛,竟然壓到第一了

#include"bits/stdc++.h"
const int N=2e5+1;
int i,n,q,p,l,r,m,a[N],x[N],c[N];
int main(){
    scanf("%d%d",&n,&q);
	for(i=1;i<=n;++i)scanf("%d",&a[i]),c[x[a[i]]=i,a[i]]++;
	for(i=1;i<=n;++i){
		l=i,r=x[a[i]],m=c[a[i]];
		while(i<r)++i,r=std::max(r,x[a[i]]),m=std::max(m,c[a[i]]);
		p+=r-l+1-m;
	}
	printf("%d",p);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章