• 0316 校赛训练赛3 解题报告


    A:

    题目:

    帽子
    Time Limit: 1000 MS Memory Limit: 32768 K
    Total Submit: 27(6 users) Total Accepted: 9(5 users) Rating:  Special Judge: No
    Description
    由字典里其他两个单词组成的单词为帽子单词,你要找到字典里所有的帽子单词。
    Input

    只有一组输入数据

    输入包含若干个小写单词,每行一个单词并且按照字典序排序。最多不超过50000个单词。每个单词长度不超过15.

    Output
    你需要按照字典序输出字典中的所有帽子单词。
    Sample Input
    cat
    catdog
    dog
    Sample Output
    catdog
    Source
    HCPC2014校赛训练赛 3
    Author
    曹振海

    这个题可以用map水过,省时的方法还是字典树

    map代码:

     1 #include<iostream>
     2 #include<string.h>
     3 #include<stdio.h>
     4 #include<map>
     5 using namespace std;
     6 
     7 map<string,int>mp;
     8 
     9 int main()
    10 {
    11     int k=0;
    12     string str[50005];
    13     //freopen("aa.txt","r",stdin);
    14     while(cin>>str[k])
    15     {
    16         mp[str[k]]=1;
    17         k++;
    18     }
    19     for(int i=0;i<k;i++)
    20     {
    21         int len=str[i].length();
    22         for(int j=1;j<len;j++)
    23         {
    24             string s1=str[i].substr(0,j);
    25             string s2=str[i].substr(j,len);
    26             if(mp[s1]==1&&mp[s2]==1){
    27             cout<<str[i]<<endl;
    28             break;
    29             }
    30         }
    31     }
    32     return 0;
    33 }
    View Code

    字典树数组模拟带代码:

     1 #include<iostream>
     2 #include<string.h>
     3 #include<stdio.h>
     4 using namespace std;
     5 
     6 const int maxn=1000005;
     7 
     8 int tire[maxn][26];
     9 int flag[maxn];
    10 int tot;
    11 
    12 void Insert(char *s,int rt)
    13 {
    14     int len=strlen(s);
    15     for(int i=0;i<len;i++)
    16     {
    17         int x=s[i]-'a';
    18         if(tire[rt][x]==0)
    19         tire[rt][x]=tot++;
    20         rt=tire[rt][x];
    21     }
    22     flag[rt]=1;
    23 }
    24 
    25 bool Find2(char *s,int rt,int i)
    26 {
    27     int len=strlen(s);
    28     for(int j=i;j<len;j++)
    29     {
    30         int x=s[j]-'a';
    31         if(tire[rt][x]==0)
    32         return false;
    33         rt=tire[rt][x];
    34     }
    35     return flag[rt];
    36 }
    37 
    38 bool Find(char *s,int rt)
    39 {
    40 
    41     int len=strlen(s);
    42     for(int i=0;i<len;i++)
    43     {
    44         int x=s[i]-'a';
    45         if(tire[rt][x]==0)
    46         return false;
    47         if(flag[rt]&&Find2(s,0,i))
    48         return true;
    49         rt=tire[rt][x];
    50     }
    51     return false;
    52 }
    53 
    54 int main()
    55 {
    56     int k=0;
    57     tot=1;
    58     char str[50005][20];
    59     //freopen("aa.txt","r",stdin);
    60     while(scanf("%s",str[k])!=EOF)
    61     {
    62         Insert(str[k],0);
    63         k++;
    64     }
    65     for(int i=0;i<k;i++)
    66     {
    67         if(Find(str[i],0))
    68         printf("%s
    ",str[i]);
    69     }
    70     return 0;
    71 }
    View Code

    字典树指针代码:

     1 #include<iostream>
     2 #include<string.h>
     3 #include<stdio.h>
     4 using namespace std;
     5 
     6 struct tire
     7 {
     8     tire *next[26];
     9     bool flag;
    10     tire()
    11     {
    12         for(int i=0;i<26;i++)
    13         {
    14             next[i]=NULL;
    15             flag=false;
    16         }
    17     }
    18 }root;
    19 
    20 void Insert(char *s)
    21 {
    22     tire *rt=&root;
    23     for(int i=0;s[i];i++)
    24     {
    25         int x=s[i]-'a';
    26         if(rt->next[x]==NULL)
    27         {
    28             rt->next[x]=new tire;
    29         }
    30         rt=rt->next[x];
    31     }
    32     rt->flag=true;
    33 }
    34 
    35 bool Find2(char *s,int i)
    36 {
    37     tire *rt=&root;
    38     for(int j=i;s[j];j++)
    39     {
    40         int x=s[j]-'a';
    41         if(rt->next[x]==NULL)
    42         return false;
    43 
    44         rt=rt->next[x];
    45     }
    46     return rt->flag;
    47 }
    48 
    49 bool Find(char *s)
    50 {
    51     tire *rt=&root;
    52     for(int i=0;s[i];i++)
    53     {
    54         int x=s[i]-'a';
    55         if(rt->next[x]==NULL)
    56         return false;
    57 
    58         if(rt->flag&&Find2(s,i))
    59         return true;
    60 
    61         rt=rt->next[x];
    62     }
    63     return false;
    64 }
    65 
    66 int main()
    67 {
    68     int k=0;
    69     char str[50005][20];
    70     //freopen("aa.txt","r",stdin);
    71     while(scanf("%s",str[k])!=EOF)
    72     {
    73         Insert(str[k]);
    74         k++;
    75     }
    76     for(int i=0;i<k;i++)
    77     {
    78         if(Find(str[i]))
    79         printf("%s
    ",str[i]);
    80     }
    81     return 0;
    82 }
    View Code

    B:

    背单词
    Time Limit: 1000 MS Memory Limit: 32768 K
    Total Submit: 47(25 users) Total Accepted: 29(24 users) Rating:  Special Judge: No
    Description

    大四了,Leyni感觉好惆怅,因为找不到工作,所以最后决定考研了,可是Leyni的英语好差,没办法,先从最基本的背单词开始吧。那么多单词怎么才好背呢,话说考研界盛传利用前缀背单词,貌似好神奇的样子。因为英语单词很多,Leyni想要知道以一个特定字符串做前缀的单词有多少,于是他来找你帮忙了。

    Input
    输入首先包含若干行小写单词,表示字典里的单词,以END结束,然后是若干个询问字符串,表示单词的前缀。输入到文件结束。最多不超过50000个单词。每个单词长度不超过15。
    Output
    对于每一个询问字符串,每行输出一个整数,表示单词表里有多少单词以此字符串作为前缀。
    Sample Input
    a
    ab
    aba
    abcaa
    END
    aba
    a
    ab
    abcd
    Sample Output
    1
    4
    3
    0
    Source
    HCPC2014校赛训练赛 3
    Author
    曹振海

    这个题同样可以用字典树和map做:

    map代码:

     1 #include<iostream>
     2 #include<string.h>
     3 #include<stdio.h>
     4 #include<map>
     5 using namespace std;
     6 
     7 map<string,int>mp;
     8 
     9 int main()
    10 {
    11     string s;
    12     //freopen("aa.txt","r",stdin);
    13     while(cin>>s)
    14     {
    15         if(s=="END")
    16         break;
    17         int len=s.length();
    18         for(int i=0;i<=len;i++)
    19         {
    20             string s1=s.substr(0,i);
    21             mp[s1]++;
    22         }
    23     }
    24     while(cin>>s)
    25     {
    26         if(s=="END")
    27         break;
    28         cout<<mp[s]<<endl;
    29     }
    30     return 0;
    31 }
    View Code

    字典树数组模拟:

     1 #include<iostream>
     2 #include<string.h>
     3 #include<stdio.h>
     4 #include<map>
     5 using namespace std;
     6 
     7 const int maxn=1000005;
     8 
     9 int tire[maxn][26];
    10 int num[maxn];
    11 int tot;
    12 
    13 void Insert(char *s,int rt)
    14 {
    15     int len=strlen(s);
    16     for(int i=0;i<len;i++)
    17     {
    18         int x=s[i]-'a';
    19         if(tire[rt][x]==0)
    20         tire[rt][x]=tot++;
    21         rt=tire[rt][x];
    22         num[rt]++;
    23     }
    24 }
    25 
    26 int Find(char *s,int rt)
    27 {
    28     int len=strlen(s);
    29     for(int j=0;j<len;j++)
    30     {
    31         int x=s[j]-'a';
    32         if(tire[rt][x]==0)
    33         return 0;
    34         rt=tire[rt][x];
    35     }
    36     return num[rt];
    37 }
    38 
    39 int main()
    40 {
    41     char s[maxn];
    42     tot=1;
    43     //freopen("aa.txt","r",stdin);
    44     while(scanf("%s",s))
    45     {
    46         if(strcmp(s,"END")==0)
    47         break;
    48         Insert(s,0);
    49     }
    50     while(scanf("%s",s)!=EOF)
    51     {
    52         printf("%d
    ",Find(s,0));
    53     }
    54     return 0;
    55 }
    View Code

    字典树指针:

     1 #include<iostream>
     2 #include<string.h>
     3 #include<stdio.h>
     4 using namespace std;
     5 
     6 const int maxn=10005;
     7 
     8 struct tire
     9 {
    10     tire *next[26];
    11     int num;
    12     tire()
    13     {
    14         for(int i=0;i<26;i++)
    15         {
    16             next[i]=NULL;
    17             num=0;
    18         }
    19     }
    20 }root;
    21 
    22 void Insert(char *s)
    23 {
    24     tire *rt=&root;
    25     for(int i=0;s[i];i++)
    26     {
    27         int x=s[i]-'a';
    28         if(rt->next[x]==NULL)
    29         {
    30             rt->next[x]=new tire;
    31         }
    32         rt=rt->next[x];
    33         rt->num++;
    34     }
    35 }
    36 
    37 int Find(char *s)
    38 {
    39     tire *rt=&root;
    40     for(int j=0;s[j];j++)
    41     {
    42         int x=s[j]-'a';
    43         if(rt->next[x]==NULL)
    44         return 0;
    45         rt=rt->next[x];
    46     }
    47     return rt->num;
    48 }
    49 
    50 int main()
    51 {
    52     char s[maxn];
    53     //freopen("aa.txt","r",stdin);
    54     while(scanf("%s",s))
    55     {
    56         if(strcmp(s,"END")==0)
    57         break;
    58         Insert(s);
    59     }
    60     while(scanf("%s",s)!=EOF)
    61     {
    62         printf("%d
    ",Find(s));
    63     }
    64     return 0;
    65 }
    View Code

    C:

    搬果子
    Time Limit: 2000 MS Memory Limit: 32768 K
    Total Submit: 22(17 users) Total Accepted: 15(15 users) Rating:  Special Judge: No
    Description
        果园里面有n堆果子,每堆果子有xi个,每个果子的重量为1,小明每次把i,j两堆果子移成一堆,需要花费的体力为xi+xj。最后移成一堆,求最小花费体力值。
    其中1<=n<=10000,1<=m<=10000。均为正整数。
    Input

        每组数据第一行输入一个正整数n,表示有n堆果子。

        接下来一行有n个正整数,表示每堆果子的重量。

        输入以EOF结尾。

    Output
        每组数据单独一行,输出所花费的最小体力值。
    Sample Input

    3

    1 2 9

    5

    1 3 9 18 30

    Sample Output

    15

    109

    Hint
     
    Source
    HCPC2014校赛训练赛 3
    Author
    BH

    这个题可以用堆或者优先队列来写

    优先队列模板:额……慢的要死

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<string.h>
     4 #include<queue>
     5 using namespace std;
     6 
     7 int main()
     8 {
     9     int n,num,ans;
    10     //freopen("aa.txt","r",stdin);
    11     while(scanf("%d",&n)!=EOF)
    12     {
    13         ans=0;
    14         priority_queue<int,vector<int>,greater<int> >q;
    15         while(n--)
    16         {
    17             scanf("%d",&num);
    18             q.push(num);
    19         }
    20         while(q.size()>1)
    21         {
    22             int a1=q.top();
    23             q.pop();
    24             int a2=q.top();
    25             q.pop();
    26             ans+=(a1+a2);
    27             q.push(a1+a2);
    28         }
    29         printf("%d
    ",ans);
    30     }
    31     return 0;
    32 }
    View Code

    堆(有点懒了,直接用的stl==)

     1 #include<iostream>
     2 #include<string.h>
     3 #include<algorithm>
     4 #include<stdio.h>
     5 #include<vector>
     6 using namespace std;
     7 
     8 const int maxn=10005;
     9 int a[maxn];
    10 
    11 bool cmp(int x,int y)
    12 {
    13     return x>y;
    14 }
    15 
    16 int main()
    17 {
    18     int n;
    19     //freopen("aa.txt","r",stdin);
    20     while(scanf("%d",&n)!=EOF)
    21     {
    22         int ans=0;
    23         for(int i=0;i<n;i++)
    24         scanf("%d",&a[i]);
    25         make_heap(a,a+n,cmp);
    26         while(n>1){
    27             pop_heap(a,a+n,cmp);
    28             pop_heap(a,a+n-1,cmp);
    29             a[n-2]+=a[n-1];
    30             ans+=a[n-2];
    31             n--;
    32             push_heap(a,a+n,cmp);
    33         }
    34         printf("%d
    ",ans);
    35     }
    36     return 0;
    37 }
    View Code

    D:

    截取方案数
    Time Limit: 1000 MS Memory Limit: 32768 K
    Total Submit: 29(14 users) Total Accepted: 18(14 users) Rating:  Special Judge: No
    Description

    给定一个模式串T,主串S,问:从S中截取T有多少种方案?

    Input

    有多组测试数据,对于每组测试数据,第一行是模式串T,第二行是主串S,数据中仅包含大小写字母和数字,模式串T长度不超过10^4, 主串S长度不超过10^5。

    注意:数据是随机的。

    Output

    对于每组测试数据,输出一行,为截取方案数。

    Sample Input
    abc
    abcdaabcab
    abcd
    abcdaabcab
    aba
    abababa
    
    Sample Output
    2
    1
    3

    kmp模板题:

    代码:

     1 #include<iostream>
     2 #include<string.h>
     3 #include<algorithm>
     4 #include<stdio.h>
     5 #include<vector>
     6 using namespace std;
     7 
     8 const int maxn=100005;
     9 char s1[maxn],s2[maxn];
    10 int next[maxn];
    11 int len1,len2;
    12 
    13 void get_next()
    14 {
    15     int i,j;
    16     next[1]=0;
    17     for (i=0,j=2;j<=len2;j++)
    18     {
    19         while(i>0&&s2[i+1]!=s2[j])
    20         i=next[i];
    21         if(s2[i+1]==s2[j])
    22         i++;
    23         next[j]=i;
    24     }
    25 }
    26 
    27 int kmp()
    28 {
    29     int i,j,res=0;
    30     for(i=1,j=0;i<=len2;i++)
    31     {
    32         while(j>0&&s1[j+1]!=s2[i])
    33         j=next[j];
    34         if(s1[j+1]==s2[i])
    35         j++;
    36         if(j==len1)
    37         {
    38             res++;
    39             j=next[j];
    40         }
    41     }
    42     return res;
    43 }
    44 
    45 int main()
    46 {
    47     //freopen("aa.txt","r",stdin);
    48     while(gets(s1+1))
    49     {
    50         gets(s2+1);
    51         len1=strlen(s1+1);
    52         len2=strlen(s2+1);
    53         get_next();
    54         printf("%d
    ",kmp());
    55     }
    56     return 0;
    57 }
    View Code

    E:

    消息队列
    Time Limit: 1000 MS Memory Limit: 32768 K
    Total Submit: 35(14 users) Total Accepted: 12(11 users) Rating:  Special Judge: No
    Description
    Windows操作系统是基于消息的,也就是说任何的事件,包括鼠标移动和点击,键盘的输入,都会被放入操作系统的消息队列中,而消息本身带有一定的参数和优先级。Windows会优先处理优先级较高的消息,当两个消息优先级相同时,按照先来先服务的原则进行处理,你的任务就是模拟这种机制。
    Input
    输入首先分为两种,GET表示从消息队列中取出一个消息。PUT表示把一个消息放入消息队列,每一个消息包含三个部分:内容,参数和优先级(数字越小优先级越高)。输入亦按照此顺序进行。消息的内容长度不会超过15。最多不超过60000个操作。
    Output
    对于每一个GET操作,若队列为空,输出EMPTY QUEUE!否则输出按照规则得到的第一个消息的内容和参数。
    Sample Input

    GET

    PUT msgone 11 6

    PUT msgtwo 8 4

    GET

    GET

    GET

    Sample Output

    EMPTY QUEUE!

    msgtwo 8

    msgone 11

    EMPTY QUEUE!

    Source
    HCPC2014校赛训练赛 3
    Author
    曹振海

    基于优先队列的基本操作

    代码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<queue>
     7 using namespace std;
     8 struct que{
     9     char str[20];
    10     int youxian,canshu,shijian;
    11 };
    12 struct cmp{
    13      bool operator()(const que &a,const que &b) {
    14                      if(a.youxian!=b.youxian)
    15                         return a.youxian>b.youxian;
    16                             return a.shijian>b.shijian;
    17                     }
    18 };
    19 int main()
    20 {
    21     priority_queue< que, vector<que>, cmp > p;
    22     char s[20],a[20];
    23     que aa;
    24     int c,y,o=0;
    25     while(~scanf("%s",&s)){o++;
    26         if(s[0]=='P'){
    27             scanf("%s",&aa.str);
    28             scanf("%d%d",&aa.canshu,&aa.youxian);
    29             aa.shijian=o;
    30             p.push(aa);
    31         }else{
    32             if(p.empty())
    33                 printf("EMPTY QUEUE!
    ");
    34             else{
    35                 aa=p.top();
    36                 printf("%s %d
    ",aa.str,aa.canshu);
    37                 p.pop();
    38             }
    39         }
    40     }
    41     return 0;
    42 }
    View Code

    F;

    最小的n个和
    Time Limit: 1000 MS Memory Limit: 32768 K
    Total Submit: 17(8 users) Total Accepted: 6(5 users) Rating:  Special Judge: No
    Description

    给定A、B两个数列,各包含n个数,分别从A和B中任意取一个数相加得到和,这样会有n^2种结果(包括重复的),求n^2个结果中前n个最小的和。

    Input

    有多组测试数据。

    对于每组测试数据,第一行为n,第二行为数列A,第三行为数列B。

    1<=n<=100000, 0 <= Ai, Bi <= 10^9。

    Output

    对于每组测试数据,输出一行,包含前n个最小的和,按照升序输出,两数之间用一个空格隔开。

    Sample Input
    5
    1 3 4 2 0
    7 3 5 2 11
    10
    74 50 47 45 38 64 19 2 84 69
    91 46 44 7 67 1 40 60 78 41
    
    Sample Output
    2 3 3 4 4
    3 9 20 26 39 42 43 45 46 46
    
    Source
    HCPC2014校赛训练赛 3

    比赛的时候没做出来,现在做出来了:

    代码:

     1 #include<iostream>
     2 #include<string.h>
     3 #include<algorithm>
     4 #include<stdio.h>
     5 using namespace std;
     6 
     7 const int maxn=100005;
     8 int a[maxn],b[maxn],c[maxn];
     9 
    10 int main()
    11 {
    12     int n;
    13     //freopen("aa.txt","r",stdin);
    14     while(scanf("%d",&n)!=EOF)
    15     {
    16         for(int i=0;i<n;i++)
    17         scanf("%d",&a[i]);
    18         for(int i=0;i<n;i++)
    19         scanf("%d",&b[i]);
    20         sort(a,a+n);
    21         sort(b,b+n);
    22         for(int i=0;i<n;i++)
    23         c[i]=a[0]+b[i];
    24         make_heap(c,c+n);
    25         for(int i=1;i<n;i++)
    26         {
    27             for(int j=0;j<n;j++)
    28             {
    29                 int x=a[i]+b[j];
    30                 if(x<c[0])
    31                 {
    32                     pop_heap(c,c+n);
    33                     c[n-1]=x;
    34                     push_heap(c,c+n);
    35                 }
    36                 else
    37                 break;
    38             }
    39         }
    40         sort_heap(c,c+n);
    41         for(int i=0;i<n;i++)
    42         printf(i==0?"%d":" %d",c[i]);
    43         printf("
    ");
    44     }
    45     return 0;
    46 }
    View Code
  • 相关阅读:
    artdialog4.1.7 中父页面给子页面传值
    Sql Server按树形结构排序查询表记录
    js控制滚动条平滑滚动到制定位置
    sql实现对多个条件分组排序方法和区别
    css渐变颜色在线制作
    c#中文转全拼或首拼
    Aspose Cells 添加数据验证(动态下拉列表验证)
    jQuery 插件autocomplete
    导出excel时,以form方式提交json数据
    asp.Net2.0中TextBox设置只读后后台获取不到值的解决方法
  • 原文地址:https://www.cnblogs.com/zhanzhao/p/3607872.html
Copyright © 2020-2023  润新知