GalaxyOJ-951 (思维)

题目

Problem 951: 多愁善感
Time Limit: 2000 ms Memory Limit: 128000 KB

Problem 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 1

3 13 5
3 2 1 3 3

3 12 8
1 1 3 3 2 2 1 1

3 9 6
3 3 1 1 3 1

2 8 7
2 5 6 3 2 1 2

2 8 4
1 6 7 4

Sample 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 爆零……
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值