zoukankan      html  css  js  c++  java
  • 2021牛客寒假算法基础集训营5 D. 石子游戏(差分/贪心)

    链接:https://ac.nowcoder.com/acm/contest/9985/D
    来源:牛客网

    题目描述

    叶妹妹很喜欢玩石头,于是这天泽鸽鸽给她出了一道石子游戏,规则是这样的:有n堆石子排成一行,其中第i堆石子有ai个,叶妹妹可以选择做无数次这种操作:每次操作把连续相邻的k个石子堆中的每堆石子数目加一,请问叶妹妹能否让每堆石子的数目都相同呢?叶妹妹觉得这题太简单了,于是丢给了聪明的你,快来解决这个问题吧!

    输入描述:

    第一行输入样例组数TT对于每组样例来说,第一行输入两个数n和k第二行输入nn个数,其中第i个数为ai【数据规模与约定】1≤T≤10,1≤n≤10^5,1≤k≤n,0≤ai≤10^9
    

    输出描述:

    输出总共T行,对于每组样例来说,如果能使每堆石子的数目都相同则输出一个整数x,x表示达到相同时的最少的操作数;否则输出−1
    

    示例1

    输入

    复制

    1
    4 3
    1 1 1 2
    

    输出

    复制

    1
    

    区间+1一眼差分,关键在于区间选择的策略。

    首先求出差分数组diff,题目描述等价于每次选取一个长度为k的区间使得diff[i] += 1, diff[i + k] -= 1,最终要diff[2~n]均为0,求最少操作次数。首先对于i: n - k + 2 ~ n的diff[i]如果有负数则无解,因为要让它变为0,操作区间的右端点会超过n + 1(注意diff[n + 1]--这样是可以的)所以这段区间只能减不能加。因此先遍历i: n - k + 2 ~ n,如果有小于0的无解,有大于0的根据差分原则先diff[i - k] += diff[i];再把diff[i]设为0.

    经过上述操作,如果有解的话diff[n - k + 2 ~ n]的值应该已经变为0了。再处理n - k + 1 ~ 2。n - k + 1这个位置要特殊处理,如果其差分值小于0的话可以直接令其等于0同时累加答案(因为diff[n + 1]可以随意搞),大于0的话和之前类似,先判断i - k是否越界再累加答案。对于i属于[2, n - k + 2)处理方法和i = n - k + 2时基本一样,不同之处在于diff[i]小于0的时候如果(n - k + 1 - i) % k == 0,那么也是可以通过操作把它变为0的,然后ans += (-diff[i]) * ((n - k + 1 - i) / k + 1)。这里比较难理解,举个例子:

    8 3
    1 1 0 1 1 1 1 1
    差分后得1 0 -1 1 0 0 0 0
    

    n - k + 2为7,此时diff[7]为0,直接跳过...直到diff[4] > 0,此时把diff[4]置0,diff[1]++。再往下是diff[3],diff[3]小于1,而3 - 3 = 0越界了。如果没有上面提到的那个处理的话会输出-1,但是真的无解吗?我们看这个序列,操作顺序是[1, 3], [3, 5], [6, 8],有解。上面提到过diff[n + 1]可以随意搞,这启发我们可以借助diff[n + 1]和diff[n - k + 1]这两个位置。还是上面那个例子,处理到diff[3]的时候把diff[3]++,这样diff[6]就得--,此时diff[6]是-1,而diff[n - k + 1]可以随意搞(影响的是diff[n + 1],无所谓),因此我们再把diff[6]++即可。对于所有的满足(n - k + 1 - i) % k == 0的i都可以这样(本质上是传递的),累加答案的时候操作次数记得注意。

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <cstdio>
    #include <vector>
    #include <queue>
    #include <map>
    #include <set>
    using namespace std;
    int n, k, a[100005], diff[100005];
    int main()
    {
    	freopen("data.txt", "r", stdin);
    	int t;
    	cin >> t;
    	while(t--)
    	{
    		cin >> n >> k;
    		bool flag = 1;
    		for(int i = 1; i <= n; i++)
    		{
    			cin >> a[i];
    			diff[i] = a[i] - a[i - 1];
    			if(i >= 2)
    			{
    				if(a[i] != a[i - 1]) flag = 0;
    			}
    		}
    		int ans = 0;
    		bool pd = 1;
    		if(!flag && n == k)
    		{
    			cout << -1 << endl;
    			continue;
    		}
    		if(flag)
    		{
    			cout << 0 << endl;
    			continue;
    		}
    		for(int i = n - k + 2; i <= n; i++)
    		{
    			if(diff[i] < 0)
    			{
    				pd = 0;
    				break;
    			}
    			if(diff[i] > 0)
    			{
    				diff[i - k] += diff[i];
    				ans += diff[i];
    				diff[i] = 0;
    			}
    		}
    
    		for(int i = n - k + 1; i >= 2; i--)
    		{
    			if(i == n - k + 1)
    			{
    				if(diff[i] < 0)
    				{
    					ans -= diff[i];
    					diff[i] = 0;
    
    				}
    				else if(diff[i] == 0)
    				{
    
    				}
    				else
    				{
    					if(i - k >= 1)
    					{
    						diff[i - k] += diff[i];
    						ans += diff[i];
    						diff[i] = 0;
    					}
    					else
    					{
    						pd = 0;
    					}
    				}
    				continue;
    			}
    			if(diff[i] < 0)
    			{
    				if((n - k + 1 - i) % k == 0)
    				{
    					ans += (-diff[i]) * ((n - k + 1 - i) / k + 1);
    					//参考
    					//8 3
    					//1 1 0 1 1 1 1 1
    
    					//差分后是1 0 -1 1 0 0 0 0
    					diff[i] = 0;
    					continue;
    				}
    				pd = 0;
    				break;
    			}
    			else if(diff[i] == 0) continue;
    			else
    			{
    				if(i - k >= 1)
    				{
    					diff[i - k] += diff[i];
    					ans += diff[i];
    					diff[i] = 0;
    				}
    				else
    				{
    					pd = 0;
    					continue;
    				}
    			}
    		}
    		if(!pd) cout << -1;
    		else cout << ans;
    		cout << endl;
    	}
    	return 0;
    }
    //4 3
    //2 1 1 1
    
  • 相关阅读:
    路由系统整合
    python操作excel
    Django models ORM基础操作--白话聊Django系列
    Django视图views--白话聊Django系列
    Django分发控制器urls--白话聊Django系列
    HTML页面布局
    一篇搞定SQLAlchemy--关系对象映射
    [LC] 538. Convert BST to Greater Tree
    [LintCode] 535. House Robber III
    [Algo] Rotate String
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/14432090.html
Copyright © 2011-2022 走看看