1. 程式人生 > 其它 >序列樹 & 貪心 & 考核補題

序列樹 & 貪心 & 考核補題

技術標籤:筆記演算法資料結構貪心演算法

CTGU ACM集訓隊第二次月考核 C題 序列樹

涉及演算法 貪心

題目描述

在O. michestep王國,有一棵名叫Habaritran的樹,樹上有一個長度為 n 的序列 a,由於樹的營養不足,序列只由 0 和 1 構成,修理工Mitchell mitt覺得序列中每個連續的長度為 k 的子串中的0 與1 數量都相同,這棵樹才看起來很nice。當然,修理工Mitchell mitt可以將序列中任何一個 0 修改成 1,也可以將任何一個1修改為0,請問修理工Mitchell mitt最少需要修改多少次,才能將這棵樹變得nice。

輸入

第一行包含兩個正整數,分別為 n和k

第二行包含 n個數,每個數為 0 或者 1

輸出

輸出一行包含一個正整數,表示最少次數,如果序列怎麼修改都不能讓這棵樹變nice,那麼輸出"-1"(不包含引號)

樣例輸入

8 3
10100010

樣例輸出

-1

資料範圍

1 <= k <= n <= 10^6

解題思路
在這裡插入圖片描述
貪心的思想主要集中在 “按b-a升序排序”, 也不難理解, 為了使修改次數最少, 排序後前半部分a比較大, 所以取b, 後半部分b比較大, 所以取a, 以此來使修剪次數最少。

附上一版我的AC程式碼:

#include<iostream>
#include<algorithm>
using namespace std; int n, k; char shu[1000000+10]; int cnt; struct point{ int cha; int a; int b;//a表示改成1,b表示改成0 }; typedef struct point P; P biao[1000000+10]; bool cmp(point x, point y) { return x.cha < y.cha; } int main() { scanf("%d%d ", &n, &k); for(int i=1;i<=n;i++) scanf("%c"
, &shu[i]); if(k%2!=0) { printf("-1"); }else { for(int i=1;i<=k;i++){ for(int j=i;j<=n;j+=k){ if(shu[j]=='0') (biao[i].a)++; } //求a的。 for(int j=i;j<=n;j+=k){ if(shu[j]=='1') (biao[i].b)++; } //求b的。 biao[i].cha = biao[i].b - biao[i].a; } sort(biao+1, biao+1+k, cmp); for(int i=1;i<=(k/2);i++){ cnt+=biao[i].b; } for(int i=(k/2)+1;i<=k;i++){ cnt+=biao[i].a; } printf("%d", cnt); } return 0; }