Codeforces 985E Pencils and Boxes(尺取法/two pointers)

传送门

题意:

给定n,k,d,表示给你n支铅笔,每支有一个权值v。现在让你把n支笔放入一些盒子中(盒子数量可以无穷大),每个盒子中至少有k支笔,而且每个盒子中的笔的max(v)-min(v)不超过d。问你能否找到一个合法的放法,可以输出"YES",否则输出"NO"。


思路:

因为对权值差有要求,所以先进行排序,排序后能放进一个盒子的笔的权值v一定是连续的。之后记录两个值,一个是can[i],表示第i支笔能否作为某一段的终点,另一个是st[i],表示第i支笔能否作为某一段的起点。如果某支笔能作为某一段的终点,那么下一支笔一定可以当做某一段的起点,最后判断最后一支笔能否作为某一段的终点(即can[n]==1是否成立)。这样可以用尺取法(即two pointers)解决:将某一段的起点定为s,终点定为e,如果①起点所在位置可以作为某一段的起点(即st[s]==1成立);②终点到起点的距离大于等于k(即e-s+1>=k);③这一段的最大值减最小值不超过d(因为从小到大排序,所以最大值减最小值不超过d等价于a[e]-a[s]<=d)这三点成立,那么说明以s为起点,e为终点是可行的,则可以把can[e]赋值为1,把st[e+1]赋值为1。在①满足的情况下,直到③不满足之前,一直把e右移(即尺取法的思想)。

以样例2为例:

初始can[0]=1,st[1]=1(笔的下标从1开始),表示第0支笔(即一个不存在的位置)可以作为某一段的起点,第1支笔可以作为某一段的起点。(x表示第0支笔的v,占位用)


此时的s=1,e=1。判断 ①(st[s]==1)成立 ②e-s+1>=k 不成立 ③a[e]-a[s]<=d成立,则将e右移(即e++)。

此时的s=1,e=2。判断 ①(st[s]==1)成立 ②e-s+1>=k 成立 ③a[e]-a[s]<=d成立,则可以将can[e]=1,st[e+1]=1,,继续将e右移(即e++)。

此时的s=1,e=3。判断 ①(st[s]==1)成立 ②e-s+1>=k 成立 ③a[e]-a[s]<=d成立,则可以将can[e]=1,st[e+1]=1,,继续将e右移(即e++)。

此时的s=1,e=4。判断 ①(st[s]==1)成立 ②e-s+1>=k 成立 ③a[e]-a[s]<=d成立,则可以将can[e]=1,st[e+1]=1,,继续将e右移(即e++)。

此时的s=1,e=5。判断 ①(st[s]==1)成立 ②e-s+1>=k 成立 ③a[e]-a[s]<=d不成立,则退出这一次的循环。s右移(s++)。

此时的s=2,e=5。判断 ①(st[s]==1)不成立,则退出这一次的循环。s右移(s++)。

此时的s=3,e=5。判断 ①(st[s]==1)成立 ②e-s+1>=k 成立 ③a[e]-a[s]<=d不成立,则退出这一次的循环。s右移(s++)。

此时的s=4,e=5。判断 ①(st[s]==1)成立 ②e-s+1>=k 成立 ③a[e]-a[s]<=d不成立,则退出这一次的循环。s右移(s++)。

此时的s=5,e=5。判断 ①(st[s]==1)成立 ②e-s+1>=k 不成立 ③a[e]-a[s]<=d成立,则e右移(e++)。

此时的s=5,e=6。判断 ①(st[s]==1)成立 ②e-s+1>=k 成立 ③a[e]-a[s]<=d成立,则可以将can[e]=1,st[e+1]=1,,继续将e右移(即e++)。

运行到结束的过程不再赘述。

可以清晰的看出变化过程中can[n]变为了1,即可以找到一种可行方案。

如果对过程还有问题的可以具体了解尺取法或者再仔细思考这样的过程。


AC代码:

/**********************************************
	Author:		StupidTurtle
	Date:		2018.5.29
	Email:		31601359@stu.zucc.edu.cn
**********************************************/

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long ll ;
const int oo = 0x7f7f7f7f ;
const int maxn = 5e5 + 5 ;
const int mod = 1e9 + 7 ;

int can[maxn] , st[maxn] , a[maxn] , n , k , d ;

int main(void){
	
	scanf("%d%d%d",&n,&k,&d );
	for ( int i = 1 ; i <= n ; i ++ )	scanf("%d",&a[i] );
	sort ( a + 1 , a + 1 + n );
	can[0] = 1 ;
	st[1] = 1 ;
	int e = 1 ;
	for ( int s = 1 ; s <= n ; s ++ ){
		if ( st[s] == 1 ){
			while ( a[e] - a[s] <= d && e <= n ){
				if ( e - s + 1 >= k ){
					can[e] = 1 ;
					st[e+1] = 1 ;
				}
				e ++ ;
			}
		}
	}
	
	if ( can[n] == 1 )	printf("YES\n");
	else	printf("NO\n");
	
	return 0 ;
}

### Codeforces 887E Problem Solution and Discussion The problem **887E - The Great Game** on Codeforces involves a strategic game between two players who take turns to perform operations under specific rules. To tackle this challenge effectively, understanding both dynamic programming (DP) techniques and bitwise manipulation is crucial. #### Dynamic Programming Approach One effective method to approach this problem utilizes DP with memoization. By defining `dp[i][j]` as the optimal result when starting from state `(i,j)` where `i` represents current position and `j` indicates some status flag related to previous moves: ```cpp #include <bits/stdc++.h> using namespace std; const int MAXN = ...; // Define based on constraints int dp[MAXN][2]; // Function to calculate minimum steps using top-down DP int minSteps(int pos, bool prevMoveType) { if (pos >= N) return 0; if (dp[pos][prevMoveType] != -1) return dp[pos][prevMoveType]; int res = INT_MAX; // Try all possible next positions and update 'res' for (...) { /* Logic here */ } dp[pos][prevMoveType] = res; return res; } ``` This code snippet outlines how one might structure a solution involving recursive calls combined with caching results through an array named `dp`. #### Bitwise Operations Insight Another critical aspect lies within efficiently handling large integers via bitwise operators instead of arithmetic ones whenever applicable. This optimization can significantly reduce computation time especially given tight limits often found in competitive coding challenges like those hosted by platforms such as Codeforces[^1]. For detailed discussions about similar problems or more insights into solving strategies specifically tailored towards contest preparation, visiting forums dedicated to algorithmic contests would be beneficial. Websites associated directly with Codeforces offer rich resources including editorials written after each round which provide comprehensive explanations alongside alternative approaches taken by successful contestants during live events. --related questions-- 1. What are common pitfalls encountered while implementing dynamic programming solutions? 2. How does bit manipulation improve performance in algorithms dealing with integer values? 3. Can you recommend any online communities focused on discussing competitive programming tactics? 4. Are there particular patterns that frequently appear across different levels of difficulty within Codeforces contests?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值