E. K-periodic Garland(贪心)

题目传送门

题意:
给你一个01串,要你对其中字符进行修改,使得修改后的01串每两个相邻的1的距离为k,只有1个1或者全是0的串也算合法串,问最小操作步数。

数据范围:

n<=1e6,k<=n

思路:
先假设全部关闭,就是cnt个,然后通过枚举余数作为第一个,以k为周期遍历,sum代表当前可减少代价,遇到1就sum++,0就sum–,通过ma维护sum的最大值,最后cnt-ma就是答案。

#include
#define endl '\n'
#define null NULL
#define ls p<<1
#define rs p<<1|1
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define vi vector
#define mii map
#define pii pair
#define ull unsigned long long
#define all(x) x.begin(),x.end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ct cerr<<"Time elapsed:"<<1.0*clock()/CLOCKS_PER_SEC<<"s.\n";
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read(){int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
return x*f;}
using namespace std;
const int N=1e6+5;
const int inf=0x7fffffff;
const int mod=998244353;
const double eps=1e-6;
signed main()
{
    int t;
	cin>>t;
	while(t--)
    {
		int n,k;
		cin>>n>>k;
		string s;
		cin>>s;
		int cnt=0;
		for(auto i:s) cnt+=i-'0';
		int ans=2e18;
		int ma=0;
		for(int i=0;i<k;i++)
        {
			int sum=0;
			for(int j=i;j<n;j+=k)
            {
				if(s[j]=='1')
                    sum++;
				else 
                    sum--;
				sum=max(0LL,sum);
				ma=max(ma,sum);
			}
		}
		cout<<cnt-ma<<endl;
	}
}

你可能感兴趣的:(数学,贪心,构造等思维问题)