码迷,mamicode.com
首页 > 其他好文 > 详细

【55测试】【字符串】【栈】【找规律】

时间:2016-11-02 00:05:00      阅读:323      评论:0      收藏:0      [点我收藏+]

标签:模拟   blog   ios   ++   ***   答案   scanf   打表   long   

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

第一题 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("\n");
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\n",ans);
52     }
53     return 0;
54 }

  明天加油!

【55测试】【字符串】【栈】【找规律】

标签:模拟   blog   ios   ++   ***   答案   scanf   打表   long   

原文地址:http://www.cnblogs.com/lx0319/p/6021143.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!