zoukankan      html  css  js  c++  java
  • 【55测试】【字符串】【栈】【找规律】

      集训第二天,额,考崩了。

    第一题 hao 大意:(这个名字就不要在意了,其实是祖玛游戏)

      模拟祖玛游戏的模式,给一个'A'~'Z'的字符串,然后有t个插入操作为 “ 添加后的在原字符串的位置 x  插入元素 c ”,字符串中有超过或等于 3 个相同的字符,则被消除,输出每次操作后剩余的字符串,如果为空,则输出“-”。

      样例:  ACCBA                      输出:  ABCCBA

            5                AABCCBA

            1 B             AABBCCBA

            0 A             -

            2 B             A

            4 C

            0 A

    解:

      先开始我用的string,但是cin>>s并不能读取输入为空的情况,所以,就用char来做。插入和删除都用strcpy来做,这个还需熟练。然后每次插入一个后,用while来判断它及不断删除后能不能再继续删除,然后删除。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define maxn 3005
     6 using namespace std;
     7 int n,pos,en;
     8 char s[maxn];
     9 bool pd(int p)
    10 {
    11     int l=strlen(s),sum1=0,sum2=0;
    12     for (int i=p+1;i<l;i++)
    13        if (s[i]==s[p]) {
    14            en=i;
    15            sum1++;
    16        }
    17        else break;
    18     for (int i=p-1;i>=0;i--)
    19        if (s[i]==s[p]) {
    20            pos=i;
    21            sum2++;
    22        }
    23        else break;
    24     if (sum1+sum2+1>=3) return true;
    25     else return false;
    26 }
    27 void work(int st)
    28 {
    29     pos=st;
    30     while (1)
    31     {
    32         en=pos;//初值 
    33         if (strlen(s)==0) return ;//判断empty 
    34         if (pd(pos)) {
    35             int len=0;char tmp[maxn];
    36             //len=en-pos+1;
    37             strcpy(tmp,s+en+1);//******
    38             strcpy(s+pos,tmp);
    39             pos--;
    40         }
    41         else return ;
    42     }
    43 }
    44 void print()
    45 {
    46     int l=strlen(s);
    47     if (l==0) {
    48         printf("-");
    49         printf("
    ");
    50     }
    51     else cout<<s<<endl;
    52     return ;
    53 }
    54 int main()
    55 {
    56     freopen("hao.in","r",stdin);
    57     freopen("hao.out","w",stdout);    
    58     s[0]=getchar();
    59     if(s[0]>='A'&&s[0]<='Z') scanf("%s",s+1);
    60     else s[0]=0;
    61     
    62     cin>>n;
    63     for (int i=1;i<=n;i++)
    64     {
    65         int x;char a[maxn];
    66         int l=strlen(s);
    67         scanf("%d%s",&x,a);
    68         strcpy(a+1,s+x);
    69         strcpy(s+x,a);
    70         work(x);
    71         print();
    72     }
    73     return 0;
    74 }
    75 /*
    76     insert
    77     char tmp[1005];
    78     strcpy(tmp+1,s+k);
    79     strcpy(s+k,tmp);
    80     
    81     delete
    82     st--end--
    83     strcpy(tmp,s+end);
    84     strcpy(s+st,tmp);    
    85     
    86     */

    第二题 kun 大意:(好吧,又来解释题目名字,就是栈排序)

      给一个数字序列,通过一个栈对这个序列进行排序,输出按最大字典序的排序后的序列。即:序列 2 1 3,可以通过 2,1入栈,输出3,再输出栈内的1,2得到最大字典序输出。而 3 1 2也可以通过一个栈,得到 3 2 1。数据保证为1~n的全排列。

    解:

      先开始不懂什么是最大字典序,然后就乱搞,一个点都没有过。最大字典序,就是第一个数为最大的,也就是n(由题中的数据保证可知),然后下一个数不一定是第二大的,而应是相对而言在栈外或者在栈首的最大的。所以可以设一个cur表示当前的相对最大,cur从n~1递减;在1~n的循环中:如果不在栈内,那就让cur之前的全部入栈,while在栈内但不在栈首,那cur--,while在栈首,就输出并且cur--,如果循环到n,就输出栈内的所有元素。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define maxn 1000005 
     6 using namespace std;
     7 int n,s[maxn],head,stak[maxn],cur;
     8 bool in[maxn];
     9 int main()
    10 {
    11     freopen("kun.in","r",stdin);
    12     freopen("kun.out","w",stdout);
    13     cin>>n;
    14     for (int i=1;i<=n;i++)
    15          scanf("%d",&s[i]);
    16     cur=n;
    17     for (int i=1;i<=n;i++)
    18     {
    19         while (in[cur]&&stak[head]!=cur) cur--;//在栈内,不能取 
    20         while (head!=0&&stak[head]>=cur)//栈顶有更优的解 
    21         {
    22             printf("%d ",stak[head]);
    23             if (stak[head]==cur) cur--;
    24             head--;
    25             while (in[cur]&&stak[head]!=cur) cur--;
    26         }
    27         if (s[i]==cur){//在栈外找到一个大的 
    28             cur--;
    29             printf("%d ",s[i]);
    30         }
    31         else {//不是优解,入栈 
    32             in[s[i]]=true;
    33             stak[++head]=s[i];
    34         }
    35         if (i==n){
    36             while (head!=0)
    37             {
    38                 printf("%d ",stak[head]);
    39                 head--;
    40             }
    41         }
    42     }
    43     return 0;
    44 }

    第三题 nan 大意:(纯粹的找规律)

      有一个序列,前三项为1 2 2,然后从第三个数开始考虑:第三个数是2 ,所以在序列里添加 2个3, 得到1 2  2 3 3;

                                第四个数是3,所以在序列里添加 3个4,得到 1 2 2 3 3 4 4  4。

      last[x]表示数字x在序列中最后出现的位置,有t个询问,输出last[last[x]];

    解:

      因为数据太大,存不下,所以打表过了30%。那么我们现在来找规律。

      1、序列: 1 2 2 3 3 4 4 4 5 5 5 6 6 6 6 7 7 7 7 8 8 8 8 9 9 9 9 9 10 10 10 10 10..........

      2、last[x]:1 3 5 8 11 15 19 23 28 33 38 44 50 56 62 69 76 83 90.......

      3、last[last[x]]:1 5 11 23 38 62 90 122.........

      那么我们把第3 行 last[last[x]]做差,此项减上一项,得到:1 4 6 12 15 24 28 32 45 50........

      改变一下就是:1*1, 2*2 ,2*3,3*4,3*5,4*6,4*7,4*8,5*9,5*10........

      即一个从1 递增的i  * 原序列 1 2 2 3 3 4 4 4 5 5.......

      再合并一些得到:1*1,2*(2+3), 3*(4+5), 4*(6+7+8),......

      每一项用等差和表示,(首项+尾项)*项数 / 2.

      然后用一个前缀和的方式记录答案。但是有可能询问的不是那一段的末尾,就需要用上一段的前缀和加上这一段。如当询问7的时候,7在 4 4 4 4中的第二个,所以就ans加上 到3 的前缀和,再加上从4开始的等差和就可以了。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define maxn 1300005
     6 #define P 1000000007
     7 #define ll long long
     8 using namespace std;
     9 ll t,sum[maxn],cur,last[maxn];
    10 struct pp{
    11     ll l,r;
    12 };
    13 pp f[maxn];
    14 void pre()
    15 {
    16     f[1].l=f[1].r=1;
    17     f[2].l=2;f[2].r=3;
    18     last[1]=1;last[2]=3;cur=2;
    19     for (ll i=3;i<=maxn+1;i++)
    20     {
    21         last[i]=last[i-1]+cur;
    22         f[i].l=last[i-1]+1;
    23         f[i].r=last[i];
    24         if (i>=last[cur]) cur++;// >=
    25     }
    26     for (ll i=1;i<=maxn+1;i++)
    27     {
    28         sum[i]=sum[i-1]+(f[i].l+f[i].r)*i*(f[i].r-f[i].l+1)/2%P;
    29         sum[i]%=P;
    30     }
    31 }
    32 int main()
    33 {
    34     freopen("nan.in","r",stdin);
    35     freopen("nan.out","w",stdout);
    36     pre();
    37     cin>>t;
    38     for (int i=1;i<=t;i++){
    39         ll x,ans=0;
    40         scanf("%I64d",&x);
    41         ll li=1,ri=maxn+1;
    42         while (li<=ri){
    43             ll mid=(li+ri)>>1;
    44             if (f[mid].r<x) li=mid+1;
    45             else ri=mid-1;
    46         }
    47         //if (f[ri].r<x) ri+=1;
    48         ans=sum[ri];
    49         ans+=(ri+1)*(x+f[ri+1].l)*(x-f[ri].r)/2%P;
    50         ans%=P;
    51         printf("%I64d
    ",ans);
    52     }
    53     return 0;
    54 }

      明天加油!

  • 相关阅读:
    [编译器] GCC编译过程 [ISO > ESc]
    《计算机网络 4》 应用层
    [编译器] cc、gcc、g++、CC的区别概括
    这个VS2010 技巧 折磨了我好久。留个贴纪念下。
    C#设置系统日期和时间的代码
    C# string格式的日期时间字符串转为DateTime类型
    中文普通图书著者号码的取号规定
    汉语著者号自动生成系统的设计与实现
    网络环境下提高图书编目工作效率搞高的方法
    jquery 超级select 插件 selectsearch v3.0.0.0插件 支持汉字、拼音、英文快速定位查询的超级select插件。可方向键、tab 键快速选择。
  • 原文地址:https://www.cnblogs.com/lx0319/p/6021143.html
Copyright © 2011-2022 走看看