題目
Problem 951: 多愁善感
Time Limit: 2000 ms Memory Limit: 128000 KBProblem Description
多愁善感的少年WSW要走過一條斑馬線,斑馬線是由n條交替的黑條和白條構成的,第一條是黑條。WSW腳的長度是s。WSW要求在走的過程中,他腳的任何一部分都不能碰到象徵邪惡的黑條。第一條之前和第n條之後的部分都是白色的,WSW可以任意選擇第一條之前的位置出發。但出發位置一旦選定,之後WSW的每一步的長度都必須是k。請你判斷WSW有沒有可能在不碰到黑條的情況下通過斑馬線,即走到第n條之後。
Input
輸入文件emotional.in有多組數據。
第一行一個整數t 表示數據組數。
每組數據的第一行有三個整數s, k, n。
第二行有n個整數A_1, A_2, …, A_n,依次表示黑白條的長度。100%的數據,
2<=n<=500000
,1<=s<k<=10^9
,1<=A_i<=10^9
,1<=t<=10
。Output
每組數據輸出一行。
若能通過輸出”TAK”,否則輸出”NIE”。Sample Input
6
3 9 10
3 3 3 1 1 3 2 1 2 13 13 5
3 2 1 3 33 12 8
1 1 3 3 2 2 1 13 9 6
3 3 1 1 3 12 8 7
2 5 6 3 2 1 22 8 4
1 6 7 4Sample Output
NIE
TAK
TAK
TAK
TAK
NIE
分析
- 把線段看成數軸上緊貼着的線段,從0開始。
- 由於每步的長度是固定的,對於每個黑色區域,區間中所有數 %k ,映射到區間
[0,k-1]
上,代表模數爲這些的點都不能走到(不然肯定會踏上黑色區域)。最後看看[0,k-1]
裏有沒有白色(沒被染黑)的點,就知道有沒有方案了。
程序
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
struct zzk{ll l,r;} a[1000005]; //區間 l,r 不可行
bool cmp(zzk x,zzk y){
if (x.l==y.l) return x.r>y.r;
return x.l<y.l;
}
ll i,t,n,s,k,l,r,len,F,kl,kr,k1,k2,num,R;
void upd(ll x,ll y){
if (y<x){return;}
kl=x/k,kr=y/k;
k1=x%k,k2=y%k;
if (y-x>=k){a[++num]=(zzk){0,k-1}; return;}
if (kl==kr){
a[++num]=(zzk){k1,k2};
return;
}
if (kr-kl==1){
a[++num]=(zzk){k1,k-1};
a[++num]=(zzk){0,k2};
return;
}
}
int main(){
for (scanf("%lld",&t),F=1; t--; F=1,num=0){
scanf("%lld%lld%lld",&s,&k,&n); //一步長 k,腳長 s
for (i=l=0; i<n && F; i++){
scanf("%lld",&len);
r=l+len,l+=1; //右端點在 [l,r] 都不行
if (~i&1) upd(l,r+s-1);
l=r;
}
sort(a+1,a+num+1,cmp);
if (a[1].l>0){puts("TAK"); continue;}
for (i=1,F=0,R=0; i<=num && !F; i++){
if (a[i].l>R+1){F=1; continue;}
R=max(R,a[i].r);
while (i<num && a[i+1].l==a[i].l) i++;
}
if ((R<k-1) || F){puts("TAK"); continue;}
puts("NIE");
}
}
提示
- 哇,測試時函數傳參開成 int ,結果 WA 爆零……