zoukankan      html  css  js  c++  java
  • P2882 Face The Right Way

    这道题没有一个比较详细的题解,我来提供一份。
    首先我们可以知道,反转区间的顺序对结果没有影响,而且一个区间如果翻转两次以上是没有意义的,所以,问题就变成了求哪些区间需要反转。
    我们枚举k。对于每一个k,我们设计一个calc函数来判断k的操作次数。
    显然的,我们可以设计出一种方法,就是每一次都检查最左端,然后进行反转,很容易写出下面的calc函数。

    int calc(int k) {
    	int ans = 0;
    	int i; 
    	for(i = 1; i + k - 1 <= N; i++) {
    		if(f[i] == 1) {
    			for(int j = i; j <= i + k - 1; j++) {
    				f[j] = !f[j];
    			}
    			ans++;
    		}
    	}
    	for(i--; i <= N; i++) {
    		if(f[i] == 1) return -1;
    	}
    	return ans;
    }
    

    这样的检查方式复杂度为O(n2),再结合枚举k,总的复杂度是O(n3),这样的复杂度可以通过70%的数据,但还不够好。
    我们来考虑怎么优化。显然的,我们没有必要去记录每一个的状态,我们只需要存储每一个区间是否反转过。所以,我们定义
    f[i]为区间[i, i+k-1]是否反转。
    这样,反转的复杂度就降到了O(1),总的复杂度就降到了O(n2),这样我们就可以AC这道题了。
    对于实现上还有一个问题,就是怎么判断每一个格子的状态,这个问题我们留给读者思考。
    下面贴上calc的代码。

    int calc(int K) {
    	memset(f, 0, sizeof(f));
    	int ans = 0;
    	int sum = 0;
    	for(int i = 0; i + K <= N; i++) {
    		if((g[i] + sum) % 2 != 0) {
    			ans++;
    			f[i] = 1;
    		}
    		sum += f[i];
    		if(i - K + 1 >= 0) sum-=f[i-K+1];
    	}
    	for(int i = N - K + 1; i < N; i++) {
    		if((g[i] + sum) % 2 != 0) {
    			return -1;
    		}
    		if(i-K+1 >= 0) {
    			sum-=f[i-K+1];
    		}
    	}
    	return ans;
    }
    

    如果有问题,可以私信。

  • 相关阅读:
    servlet技术学习随笔
    python使用openpyxl读取excel文件
    课后作业-阅读任务-阅读提问-3
    课后作业-阅读任务-阅读提问-2
    课后作业-阅读任务-阅读笔记3
    构建之法:现代软件工程-阅读笔记2
    《构建之法:现代软件工程-阅读笔记》
    结对编程需求分析
    团队-团队编程项目作业名称-需求分析
    团队-团队编程项目作业名称-成员简介及分工
  • 原文地址:https://www.cnblogs.com/gengchen/p/6037925.html
Copyright © 2011-2022 走看看