hdu 6387 AraBellaC

Problem Description
Princess Arabella loves the letter C, which earned her the epithet ArraBellaC. She would like to endeavor to construct a periodic string with length n(n≤20000) to spare her tedious time. In every period of the string, the substring begins with dozens of As and ends with dozens of Cs, and dozens of Bs are inserted between them, and the number of A, B, C is a, b, c.(For example, if a=1, b=1, c=2 then one of the period of the string is ABCC, and the periodic string is ABCCABCC……).Note that in the last period of the string, the substring can be incomplete and the last few letters of the period can be cut down.

And now, Arabella has constructed a periodic string, she want to give you a question: if she tells you the character is Ci(Ci∈{A,B,C}) in the Xi(Xi≤10000) , then could you tell her the value of a,b,c? If there are multiple answers, please find the lexicographically smallest answer. If you can’t find a valid answer, please print NO

Input
The first line gives an integer T(1≤T≤40) , which indicates the number of cases in the input.
The first line of every case contains only one integer m(1≤m≤5000), which means the number of characters AraBella told you.
A number Xi(1≤Xi≤10000) and a letter Ci are given in the following m lines, which means the position Xi in the string with letter Ci.

Output
Print a,b,c in order. If there are multiple answers, please find the lexicographically smallest answer. If you can’t find a valid answer, please print NO.(It is gratuated that 0<a,b,c, and please forget my poor Yinglish)

Sample Input
2
3
1 A
2 B
3 C
4
1 A
2 C
3 B
4 C

Sample Output
1 1 1
NO

题意:设x代表至少有一个x字符,构造一个串s: abc,然后s一直重复,要求:题目给出的条件,即,第几位必须是什么字符,
做法:枚举串的长度,对于某一个长度l,把串切成多个长度为l的子串,按照题意这写子串必定是相同的,那么记录a出现最右边的位置qa,b出现最左边的位置qbl,b出现最右边的位置qbr,c出现最左边的位置,如果qbl>qa&&qbr < qc;则对于这个长长度有某个串s使条件成立,
实现:对于某一段出现最左边最右边,应为长度至多为10000,那么建立3个数组,某个区间最大最小值就是上面提到的位置了,用st表预处理,查询是o(1),查询次数是调和级数的复杂度为nlogn。

#include<bits/stdc++.h>
using namespace std;
const int N= 10005;
int lg[N];

struct node{
    int st[N][20];
    int n;
    bool tmp;
    void init(int nx,int *p,bool tp){
        n = nx;tmp = tp;
        for(int i = 1;i <= n;i ++){
            if(!p[i] && !tp){
                p[i] = 100001;
            }
            st[i][0] =p[i];
        }
        int lg2 = lg[n];
        for(int i= 1;i <= lg2;i ++){
            for(int j = 1;j <= n;j ++){
                if(j+(1<<i) <= n+1)
                    st[j][i] = get(st[j][i-1],st[j+(1<<i-1)][i-1]);
                else st[j][i] = st[j][i-1];
            }
        }
    }
    int get(int a,int b){
        if(tmp) return max(a,b);
        else return min(a,b);
    }
    int query(int l,int r){
        r = min(r,n);
        int lg2 = lg[r-l+1];
        return get(st[l][lg2],st[r+1-(1<<lg2)][lg2]);
    }
}a,bl,br,c;
vector<int> va,vb,vc;

void init(){
    int np = 2;
    lg[1] = 0;
    for(int i = 2;i < N;i ++){
        lg[i] = lg[i-1];
        if(i > np) lg[i]++,np*=2;
    }
}

int num[N];
int main(){
    init();
    int T;
    cin >> T;
    while(T--){
        int m;
        scanf("%d",&m);
        va.clear(),vb.clear(),vc.clear();
        for(int i = 1;i <= m;i ++){
            int x;
            char st[10];
            scanf("%d %s",&x,st);
            if(st[0] == 'A') va.push_back(x);
            else if(st[0] == 'B') vb.push_back(x);
            else vc.push_back(x);
        }
        memset(num,0,sizeof(num));
        for(int i = 0;i < va.size();i ++) num[va[i]] = va[i];
        a.init(10000,num,true);
        memset(num,0,sizeof(num));
        for(int i = 0;i < vb.size();i ++) num[vb[i]] = vb[i];
        br.init(10000,num,true);
        bl.init(10000,num,false);
        memset(num,0,sizeof(num));
        for(int i = 0;i < vc.size();i ++) num[vc[i]] = vc[i];
        c.init(10000,num,false);
        bool tmp = false;
        for(int i= 3;i <= 10000;i ++){
            int qa = 0,qbl = i+1,qbr = -1,qc = i+1;
            for(int j= 1;j <= 10000;j += i){
                qa = max(qa,a.query(j,j+i-1)-j+1);
                qbl = min(qbl,bl.query(j,j+i-1)-j+1);
                qbr = max(qbr,br.query(j,j+i-1)-j+1);
                qc = min(qc,c.query(j,j+i-1)-j+1);
            }
            if(qbl <= qa || qbr >= qc) continue;
            else{
                if(qbl > qbr){
                    qa = max(qa,1);
                    qc = i-1-qa;
                }
                else{
                    qa = max(qa,1);
                    qc = i-qbr;
                }
                if(qa+qc == i) continue;
                if(!qa || !qc) continue;
                printf("%d %d %d\n",qa,i-qa-qc,qc);
                tmp =true;
                break;
            }
        }
        if(tmp == false)puts("NO");
    }


    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值