NOIP2017模拟赛 senior 6.29 T2 小T的钢琴(piano)

Posted 唯莫

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIP2017模拟赛 senior 6.29 T2 小T的钢琴(piano)相关的知识,希望对你有一定的参考价值。

NOIP2017模拟赛 senior 6.29 T2 小T的钢琴(piano)

Description

Input

Output

这道题思路还是比较好想的,因为题目中已经提到公共子序列长度,所以咯,最长公共子序列好不好!

But,这里我们如果只使用LCS的话那么,这里我们的时间复杂度是O(n^2)。爆了对不对?

怎么优化呢?

对于我们的比较,在这里是比较的字符串对吧,即每一坨音符。使用string可直接比较,所以常数会小一点。

更好一点的优化就是使用哈希表,我们将乐谱Little_T中的字符串哈希,转成数值,然后通过哈希值判断,将乐谱B中的无效的音符去除。这里直接比较哈希值,常数更小。

但是,我们还是不能拿满分对吧。

我们再来优化!

题目中有提到:因为小T是一个放荡不羁的作曲家,所以保证他的乐谱中每个音符都不会重复出现。

看到这里我们是不是还可以优化呢?

有了这个条件,我们可以把LCS问题传唤成LIS(最长上升子序列)问题。

预处理还是一样的,哈希,不过我这里较为简便的直接将每一个字符转换为数值后,如果继续有字符需要加入,那么我们将先前数值乘10再相加。

我们使用二分查找,将乐谱B中数值拿入Little_T中去找,找不到,跳过。

找到了,我们从这里开始使用LIS求解就好了。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 #include<string>
  7 #define INT_MAX_ 0x7fffffff
  8 #define LONG_MAX_ 0x7fffffffffffffffll
  9 #define pi acos(-1)
 10 #define N 100010
 11 #define M 200010
 12 using namespace std;
 13 
 14 inline int read()
 15 {
 16     int data=0,w=1;
 17     char ch=0;
 18     while(ch!=\'-\' && (ch<\'0\' || ch>\'9\')) ch=getchar();
 19     if(ch==\'-\') w=-1,ch=getchar();
 20     while(ch>=\'0\' && ch<=\'9\') data=data*10+ch-\'0\',ch=getchar();
 21     return data*w;
 22 }
 23 
 24 inline void write(int x)
 25 {
 26     if(x<0) putchar(\'-\'),x=-x;
 27     if(x>9) write(x/10);
 28     putchar(x%10+\'0\');
 29 }
 30 
 31 struct Data
 32 {
 33     int value,number;
 34 } data[N];
 35 inline bool my_comp(const Data &a, const Data &b)
 36 {
 37     return a.value < b.value;
 38 }
 39 
 40 int b[M],ans[N];
 41 char Little[25];
 42 char str[25];
 43 int n,r;
 44 
 45 int main()
 46 {
 47     freopen("piano.in","r",stdin);
 48     freopen("piano.out","w",stdout);
 49 
 50     n = read();
 51     r = read();
 52     for(int i = 1; i <= n; i++)
 53     {
 54         scanf("%s",Little);
 55         int lenth = strlen(Little);
 56         data[i].number = i;
 57         data[data[i].number].value = (Little[0] - \'A\' + 1) * 10 + Little[1] - \'0\';
 58         if(lenth > 2 && Little[2] == \'.\')
 59         {
 60             for(int j = 3; j < lenth; j++)
 61             {
 62                 if(Little[j] == \'(\' || Little[j] == \'[\' || Little[j] == \'{\') break;
 63                 data[i].value = data[i].value * 10 + Little[j] - \'0\';
 64             }
 65         }
 66     }
 67     sort(data+1,data+1+n,my_comp);
 68     while(r--)
 69     {
 70         int li = read();
 71         for(int i = 1; i <= li; i++)
 72         {
 73             scanf("%s",str);
 74             int lenth = strlen(str);
 75             b[i] = (str[0] - \'A\' + 1) * 10 + str[1] - \'0\';
 76             if(lenth > 2 && str[2] == \'.\')
 77             {
 78                 for(int j = 3; j < lenth; j++)
 79                 {
 80                     if(str[j] == \'(\' || str[j] == \'[\' || str[j] == \'{\') break;
 81                     b[i] = b[i] * 10 + str[j] - \'0\';
 82                 }
 83             }
 84         }
 85         ans[0] = 0;
 86         for(int i = 1; i <= li; i++)
 87         {
 88             int left = 1, right = n;
 89             while(left < right)
 90             {
 91                 int mid = (left + right) / 2;
 92                 if(data[mid].value >= b[i])
 93                 {
 94                     right = mid;
 95                 }
 96                 else
 97                 {
 98                     left = mid + 1;
 99                 }
100             }
101             if(data[left].value != b[i]) continue;
102             if(ans[ans[0]] < data[left].number) ans[++ans[0]] = data[left].number;
103             else
104             {
105                 int aider = lower_bound(ans+1,ans+1+ans[0],data[left].number) - ans;
106                 ans[aider] = data[left].number;
107             }
108         }
109         printf("%.6lf\\n",ans[0] * 1.0 / li);
110     }
111 
112     return 0;
113 }

 

以上是关于NOIP2017模拟赛 senior 6.29 T2 小T的钢琴(piano)的主要内容,如果未能解决你的问题,请参考以下文章

NOIP2017模拟赛 senior 6.29 T1 码灵鼠(A)

NOIP模拟赛 6.29

2017.07.16【NOIP提高组】模拟赛B组 卫星照片 题解

2017.12.09NOIP提高组模拟赛A组

NOIP2017练习跳跃切除子序列(模拟)

2017-8-31 NOIP模拟赛(校内测)