【NOIP2017提高组模拟6.29】小T的钢琴

21 篇文章 0 订阅
14 篇文章 0 订阅

Description

这里写图片描述

Input

这里写图片描述

Output

R行,每行一个实数表示答案

Sample Input

9 3
A1 B2 C3 D4 E5 D4.0 C3.0 B2.0 A1.0[nya]
3 A1 A1.0 E5[qwerty]
5 B1{poi} B2 C3 A2 A1
7 C3 D4 E5 D4.0 C3.0 B2.0 A1.0[nyanya]

Sample Output

0.666667
0.400000
1.000000

Data Constraint

这里写图片描述

Hint

这里写图片描述

Solution

这题输入比较麻烦
不过我大C++直接输入就行了,什么判断都不用
题目保证第一个乐谱每个字符串只会出现一次,那就用hash(map)把它存好,然后分别匹配做最长公共子序列即可

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define N 20
#define L 201000
#define M 10100000
#define ll long long
using namespace std;
int a[2][L],d[L],h[M],b[2][M],n,m;
ll E[8];
int hash(char s[N],int l)
{
    ll x=s[1]-65;
    x=x*E[6]*8ll;
    ll y=s[2]-49;
    y=y*E[6];
    if(l>3)
    {
        fo(j,4,l)
        {
            y=y+E[9-j]*(ll)(s[j]-47);
        }
    }
    y+=x;
    int z=y%M;
    while(h[z]!=0&&h[z]!=y) z=(z+1)%M;
    h[z]=y;
    return z;
}
void work(int jy)
{
    if(jy==1) scanf("%d",&m);
    char s[N];
    fo(i,1,m)
    {
        scanf("%s ",s+1);
        int l=strlen(s+1);
        if(s[l]==']'||s[l]=='}'||s[l]==')'||s[l]=='>')
        {
            while(s[l]!='['&&s[l]!='{'&&s[l]!='('&&s[l]!='<') l--;
            l--;
        }
        int x=hash(s,l);
        a[jy][i]=x;b[jy][x]=i;
    }
}
int get(int jy)
{
    int l=0,r=d[0];
    while(l+1<r)
    {
        int m=(l+r)/2;
        if(d[m]<jy) l=m;else r=m;
    }
    if(d[r]<jy) l=r;return l;
}
int main()
{
    int ac;scanf("%d%d\n",&n,&ac);
    E[0]=1;fo(i,1,6) E[i]=E[i-1]*11ll;
    m=n;work(0);
    for(;ac;ac--)
    {
        work(1);
        memset(d,0,sizeof(d));
        fo(i,1,m)
        {
            int x=a[1][i];
            if(b[0][x]==0) continue;
            x=b[0][x];
            if(d[d[0]]<x) d[++d[0]]=x;
            else
            {
                int y=get(x);
                d[y+1]=x;
            }
        }
        printf("%.6lf\n",d[0]*1.0/m);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值