题意

AraBellaC

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 277    Accepted Submission(s): 100


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 `A`s and ends with dozens of `C`s, and dozens of `B`s 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
 

Source
 

Recommend
chendu
 

Statistic | Submit | Discuss | Note

分析

参照616156的题解。

题解又在卖萌了。。要用RMQ?。。。估计他自己没想清楚吧。。。这题哪用得着RMQ啊。。。

首先,可以暴力枚举循环节的长度:
然后,对每种字母进行判断,求出每个循环节中B,C最靠前的位置和A,B最靠后的位置。
如果A最靠后的位置在B最靠前的后面,或者B最靠后的位置在C最靠前的后面。就说明当前这个循环节长度是矛盾的。

如果不矛盾,则将A最靠后的位置及以前,都设为A,B最靠后的位置及以前(除去A的部分)都设为B,C则填充这个循环节剩余的位置。就能保证是当前长度循环节中,答案字典序最小一种方案。

问题就在于如何处理:“每个循环节中B,C最靠前的位置和A,B最靠后的位置”
可以利用调和级数:暴力枚举每个循环节,O(1)求出当前循环节最靠前的B、C,最靠后的A、B。总的时间复杂度就是O(N ln N)。

题解的方法说要用RMQ求这个问题。。。
其实就用前缀和后缀的思想不就行了?

对于每个点,它前面最近的一个A、B字母的位置,以及它后面最靠近的一个B、C字母的位置。这两个东西可以O(N)递推求出来

询问某个循环节时,求出其左端点及以后,最靠前的B、C,以及其右端点及以前最靠后的A、B即可(就是上面维护的那两个东西)。

代码

#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
    rg T data=0,w=1;
    rg char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        data=data*10+ch-'0',ch=getchar();
    return data*w;
}
template<class T>il T read(rg T&x){
    return x=read<T>();
}
typedef long long ll;
using namespace std;
co int N=1e4;
int a[N+10],pre[N+10][4],las[N+10][4],ans[4],ans1[4];
char s[20];
int get_pre(int len,int x){
    int res=len;
    for(int i=1;i<=N;i+=len){
        int t=las[i][x];
        if(t>=i+len) continue;
        res=min(res,t-i+1);
    }
    return res;
}
int get_las(int len,int x){
    int res=0;
    for(int i=1;i<=N;i+=len){
        int top=min(i+len-1,N);
        int t=pre[top][x];
        if(t<i) continue;
        res=max(res,t-i+1);
    }
    return res;
}
int main(){
//  freopen(".in","r",stdin),freopen(".out","w",stdout);
    int kase=read<int>();
    while(kase--){
        int m=read<int>();
        memset(ans,-1,sizeof ans);
        memset(a,0,sizeof a);
        memset(pre,0,sizeof pre);
        memset(las,0x3f,sizeof las);
        for(int i=1,pos;i<=m;++i){
            read(pos);scanf("%s",s);
            a[pos]=s[0]-'A'+1;
        }
        for(int i=1;i<=N;++i)
            for(int j=1;j<=3;++j){
                if(a[i]==j) pre[i][j]=i;
                pre[i][j]=max(pre[i][j],pre[i-1][j]);
            }
        for(int i=N;i>=1;--i)
            for(int j=1;j<=3;++j){
                if(a[i]==j) las[i][j]=i;
                las[i][j]=min(las[i][j],las[i+1][j]);
            }
        for(int len=3;len<=N;++len){
            int lasx=0;
            bool flag=0;
            for(int j=1;j<=3;++j){
                if(j!=1){
                    int prex=get_pre(len,j);
                    if(prex<=lasx) {flag=1;break;}
                }
                if(j!=3){
                    lasx=max(lasx+1,get_las(len,j));
                    ans1[j]=lasx;
                }
                else ans1[j]=len;
            }
            if(flag==0){
                for(int j=1;j<=3;++j){
                    if(ans1[j]<ans[j]||ans[j]==-1){
                        ans[1]=ans1[1],ans[2]=ans1[2],ans[3]=ans1[3];
                        break;
                    }
                    if(ans1[j]>ans[j]) break;
                }
            }
        }
        if(ans[1]!=-1) printf("%d %d %d\n",ans[1],ans[2]-ans[1],ans[3]-ans[2]);
        else puts("NO");
    }
    return 0;
}

HDU6387 AraBellaC的更多相关文章

  1. 2018 Multi-University Training Contest 7 Solution

    A - Age of Moyu 题意:给出一张图,从1走到n,如果相邻两次走的边的权值不同,花费+1, 否则花费相同,求最小花费 思路:用set记录有当前点的最小花费有多少种方案到达,然后最短路 #i ...

随机推荐

  1. JAVA反射会降低你的程序性能吗?

    原文出处 早两天写了<从把三千行代码重构成15行代码谈起>这篇文章,看到评论中有一些同学的回复还是在质疑反射的性能,好像程序用上了反射,就像开上了拖拉机似的.本来我觉得这个话题没有什么好讨 ...

  2. android--------AndroidStudio 关闭 Install Run

    前面讲热修复的时候说到了一个 AndroidStudio关闭Instant Run的问题 ,今天来简单的写一下. Android Studio 工具中是有很多好东西的,要全部的知道的话,还是要下点功夫 ...

  3. input不记录之前输入的值

    autocomplete="off" // input中添加这个属性

  4. 秒杀多线程第三篇 原子操作 Interlocked系列函数

    上一篇<多线程第一次亲密接触 CreateThread与_beginthreadex本质区别>中讲到一个多线程报数功能.为了描述方便和代码简洁起见,我们可以只输出最后的报数结果来观察程序是 ...

  5. EBS R12 MOAC原理探索 (转)

    转载地址 EBS R12 MOAC原理探索

  6. mysql禁止远程访问的解决办法

      1. 改表法. 可能是你的帐号不允许从远程登陆,只能在localhost.这个时候只要在localhost的那台电脑,登入mysql后,更改 "mysql" 数据库里的 &qu ...

  7. kill word out 1

    1● de 使~~ 成为 :离开 ,去掉,向下,变慢   2● dif 不,分开 ,否定,离开     3● deci 十分之一   4● deca 向下,离开   5● deca 十   6● di ...

  8. css中 font常用的样式属性

    今天我总结一下文本常用的字体样式 1.font常用样式 1)字体类型 语法:font-family: +字体类型:    如: font-family:宋体; 2)字体大小 语法:font-size: ...

  9. httpclient httpclient使用连接池

    httpclient使用连接池 http协议是无状态的,但毕竟是基于tcp的,底层还是需要和服务器连接的, 对于需要从同一个站点抓取大量网页的程序,应该使用连接池,否则每次抓取都和web站点建立连接, ...

  10. linux processes identifiers

    Linux, like all Unix uses user and group identifiers to check for access rights to files and images ...