Description
中二少年cenbo幻想自己有Eternal Feather。他认为自己的走的每一步都是一次Emotional Flutter。
现在cenbo要走过一条斑马线,斑马线是由n条交替的黑条和白条构成的,第一条是黑条。cenbo脚的长度是s。cenbo要求在走的过程中,他脚的任何一部分都不能碰到象征邪恶的黑条。第一条之前和第n条之后的部分都是白色的,cenbo可以任意选择第一条之前的位置出发。但出发位置一旦选定,之后cenbo的每一步的长度都必须是k。请你判断cenbo有没有可能在不碰到黑条的情况下通过斑马线,即走到第n条之后。
Input
输入文件emotional.in有多组数据。
第一行一个整数t 表示数据组数。
每组数据的第一行有三个整数s, k, n。
第二行有n个整数
A1,A2,...,An
A
1
,
A
2
,
.
.
.
,
A
n
,依次表示黑白条的长度。
Output
每组数据输出一行。
若能通过输出”TAK”,否则输出”NIE”。
Sample Input
2
2 8 7
2 5 6 3 2 1 2
2 8 4
1 6 7 4
Sample Output
TAK
NIE
Data Constraint
30%的数据,
n<=1300
n
<=
1300
;
50%的数据,
n<=22000
n
<=
22000
;
100%的数据,
2<=n<=500000,1<=s<k<=109,1<=Ai<=109,1<=t<=10。
2
<=
n
<=
500000
,
1
<=
s
<
k
<=
10
9
,
1
<=
A
i
<=
10
9
,
1
<=
t
<=
10
。
数据有梯度。输入文件较大请使用读入优化。
分析:
一道好水的题,结果炸了。
显然如果
x
x
这个位置不能走,那么这个位置也不能走。
那么我们可以把不能走的段映射到
[0,k)
[
0
,
k
)
,然后判断这个段是否有连续的
s
s
个位置都合法即可。
直接给段左端点一下,乱搞即可。
因为如果一个段大小大于等于
k
k
<script type="math/tex" id="MathJax-Element-13">k</script>,就可以直接退掉,但是退掉之后要把这个数据剩下的数读入完才行,然后我就这样炸了。
代码:
#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
const int maxn=1e6+7;
using namespace std;
int n,test,r,k,d,x,y,s,t,cnt;
int flag;
struct node{
int l,r;
}a[maxn];
bool cmp(node x,node y)
{
return x.l<y.l;
}
void calc()
{
scanf("%d%d%d",&r,&k,&n);
cnt=0; d=0;
flag=0;
for (int i=1;i<=n;i++)
{
scanf("%d",&y);
if (flag) continue;
if (i%2==0)
{
d=(d+y)%k;
continue;
}
if (y>=k)
{
flag=1;
continue;
}
x=d,y=d+y-1;
d=(y+1)%k;
s=x/k,t=y/k;
if (s<t)
{
a[++cnt]=(node){x%k,k-1};
a[++cnt]=(node){0,y%k};
}
else a[++cnt]=(node){x%k,y%k};
}
sort(a+1,a+cnt+1,cmp);
int ans=0,p=-1;
for (int i=1;i<=cnt;i++)
{
ans=max(ans,a[i].l-p-1);
p=max(p,a[i].r);
}
ans=max(ans,a[1].l+k-p-1);
if ((ans>=r) && (!flag)) printf("TAK\n");
else printf("NIE\n");
}
int main()
{
freopen("emotional.in","r",stdin);
freopen("emotional.out","w",stdout);
scanf("%d",&test);
while (test--) calc();
}