码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj2217 [Poi2011]Lollipop

时间:2018-06-13 11:58:17      阅读:164      评论:0      收藏:0      [点我收藏+]

标签:输出   ...   print   ipo   amp   oid   编号   zoj   max   

[Poi2011]Lollipop

Time Limit: 15 Sec Memory Limit: 64 MBSec Special Judge

Description

有一个长度为n的序列a1,a2,...,an。其中ai要么是1("W"),要么是2("T")。
现在有m个询问,每个询问是询问有没有一个连续的子序列,满足其和为q。

Input

第一行n,m (1<=n,m<=1000000)
第二行这个序列,起始编号为1,终止编号为n
下面每行一个询问q,询问有没有一个连续的子序列,满足其和为q (1<=q<=2000000)

Output

对于每个询问,输出一行,如果有,输出这个序列的起点和终点(如果有多个输出任意一个);如果没有,输出“NIE”。

Sample Input

5 3

TWTWT

5

1

7

Sample Output

1 3

2 2

NIE



大概就是有一些想法,比如如果一个奇数能被凑出来,那么比这个奇数小的奇数也一定能够凑出来。。。。偶数同理。
然后呢还有一个就是任何一个区间都可以从【1,x】这个区间整体平移几位凑出来。再进一步说,如果说你要凑t,那么要么有一个【1,x】直接满足,要么有一个【1,x】为t+1
然后呢你就开始平移,直到左边减去的一个和右边加的一个一个1一个2就凑出来了。



#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 6;
struct ld{
    int data, tw;
}num[maxn];
char s[maxn];
int n, m, x, lpd, sum1, sum2, f[maxn * 2], lll[maxn * 2], rrr[maxn * 2];

inline void putit()
{
    scanf("%d%d", &n, &m); scanf("%s", s + 1);
    for(int i = 1; i <= n; ++i){
        if(s[i] == 'W') num[i].data = 1;
        if(s[i] == 'T') num[i].data = 2;
    }
    for(int i = n; i >= 1; --i){
        num[i].tw = num[i + 1].tw + 1;
        if(s[i] == 'W') num[i].tw = 0;
    }   
}

void workk()
{
    int sum = 0;
    for(int i = 1; i <= n; ++i){
        sum += num[i].data;
        if(s[i]=='T')
        {
            if(num[1].tw < num[i].tw)
                lll[sum - 1] = num[1].tw + 2, rrr[sum - 1] = i + num[1].tw;
            else if(i + num[i].tw != n + 1)
                lll[sum - 1] = 1 + num[i].tw, rrr[sum - 1] = i + num[i].tw;
        }
    }
}

inline void prepare()
{
    int lin = 0; 
    for(int i = 1; i <= n; ++i){
        lin += num[i].data;
        f[lin] = i; 
        lll[lin] = 1; rrr[lin] = i;     
    } 

    sum1 = lin;
    int lin1 = sum1, lin2 = sum1;
    for(int i = 1; i <= n; ++i){
        lin1 -= num[i].data;
        if(num[i].data == 1) break;
    }
    for(int i = n; i >= 1; --i){
        lin2 -= num[i].data;
        if(num[i].data == 1) break;
    }
    sum2 = max(lin1, lin2);
}

int main()
{
    //freopen("data.in", "r", stdin);
    //freopen("lpl.out", "w", stdout);
    putit();
    prepare();
    workk();
    for(int i = 1; i <= m; ++i){
        scanf("%d", &x);
        if(lll[x] == 0) puts("NIE");
        else printf("%d %d\n", lll[x], rrr[x]);
    }
    return 0;
}

bzoj2217 [Poi2011]Lollipop

标签:输出   ...   print   ipo   amp   oid   编号   zoj   max   

原文地址:https://www.cnblogs.com/LLppdd/p/9175966.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!