tj:我們發現,每一次走過的步長都是k,設當前走的步數是x,走到了一個白條

那麼,每一次走就是把所有黑條都向前移k位,我們可以考慮把所有黑條的左邊界不斷的向前移動k,直到下一次移動時,其左邊界小於0,則我們進行的操作實際上是把邊界模k

這樣子,我們得到的所有黑條就是介於[0,k-1]中的。當然有些黑條由於跨過了1個分界線而導致變成2個區間

最後判斷有沒有連續的長度大於等於s的區間即可,注意,整個區間是環形的,要加上最後一條黑條和第一條黑條對答案的影響

注意無解的情況:當有黑條的長度大於k或者k<s都無解

代碼:

#include<bits/stdc++.h>
using namespace std;
struct no{
	int x,y;
	bool operator <(const no &rhs)const{
		return x<rhs.x||x==rhs.x&&y<rhs.y;
	}
}t[1000010];
int a[1000010],ct,s,k,n;
int main(){
	freopen("emotional.in","r",stdin);
	freopen("emotional.out","w",stdout);
	int T;
	scanf("%d",&T);
	while(T--){
		int ok=0;
		scanf("%d%d%d",&s,&k,&n);
		ct=0;
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]);
		for(int i=1;i<=n;i++)
			if((i&1)&&k<=a[i]&&!ok){
				printf("NIE\n");
				ok=1;
				continue;
			}
		if(ok)continue;
		int las=0;
		for(int i=1;i<=n;i++){
			las+=a[i];
			if(i&1){
				int l=las-a[i],r=las-1;
				las%=k;
				if((l/k)<(r/k)){
					t[++ct]=(no){0,r%k};
					t[++ct]=(no){l%k,k-1};
				}
				else t[++ct]=(no){l%k,r%k};
			}
		}
		if(s>k){
			printf("NIE\n");
			continue;
		}
		sort(t+1,t+ct+1);
		las=-1;
		int r=-1e9;
		for(int i=1;i<=ct;i++){
			r=max(r,t[i].x-las-1);
			las=max(las,t[i].y);
		}
		r=max(r,t[1].x+k-1-las);
		if(r>=s)printf("TAK\n");
		else printf("NIE\n");
	}
}
05-11 13:36