jzoj 5832.【省选模拟8.20】Emotional Flutter 乱搞

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 这个位置不能走,那么x mod k这个位置也不能走。
那么我们可以把不能走的段映射到 [0,k) [ 0 , k ) ,然后判断这个段是否有连续的 s s 个位置都合法即可。
直接给段左端点sort一下,乱搞即可。
因为如果一个段大小大于等于 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();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值