CCF历届真题练习答案整理(四)

问题描述
  某股票交易所请你编写一个程序,根据开盘前客户提交的订单来确定某特定股票的开盘价和开盘成交量。
  该程序的输入由很多行构成,每一行为一条记录,记录可能有以下几种:
  1. buy p s 表示一个购买股票的买单,每手出价为p,购买股数为s。
  2. sell p s 表示一个出售股票的卖单,每手出价为p,出售股数为s。
  3. cancel i表示撤销第i行的记录。
  如果开盘价为p 0,则系统可以将所有出价至少为p 0的买单和所有出价至多为p 0的卖单进行匹配。因此,此时的开盘成交量为出价至少为p 0的买单的总股数和所有出价至多为p 0的卖单的总股数之间的较小值。
  你的程序需要确定一个开盘价,使得开盘成交量尽可能地大。如果有多个符合条件的开盘价,你的程序应当输出最高的那一个。
输入格式
  输入数据有任意多行,每一行是一条记录。保证输入合法。股数为不超过10 8的正整数,出价为精确到恰好小数点后两位的正实数,且不超过10000.00。
输出格式
  你需要输出一行,包含两个数,以一个空格分隔。第一个数是开盘价,第二个是此开盘价下的成交量。开盘价需要精确到小数点后恰好两位。
样例输入
buy 9.25 100
buy 8.88 175
sell 9.00 1000
buy 9.00 400
sell 8.92 400
cancel 1
buy 100.00 50
样例输出
9.00 450
评测用例规模与约定
  对于100%的数据,输入的行数不超过5000。

//模拟
 1  #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 using namespace std;
 7 struct node
 8 {
 9      string s;
10     double a;
11      long long b;
12 };
13 node n[5007],n1[5007],n2[5007];
14 bool flag[5007];
15 int num,num1,num2;
16 long long ans_num;
17 double ans_price;
18 bool cmp1(node n11,node n22)
19 {
20     if(n11.a!=n22.a) return n11.a<n22.a;
21     else if(n11.a==n22.a)
22     {
23         return n11.b>=n22.b;}
24 }
25 bool cmp2(node n11,node n22)
26 {
27     if(n11.a!=n22.a) return n11.a>n22.a;
28     else if(n11.a==n22.a) return n11.b>=n22.b;
29 }
30 void slove()
31 {
32     long long sum1=0,sum2=0;double price;
33     int j=0;
34     for(int i=0;i<num1;i++)
35     {
36         price=n1[i].a;
37         sum1+=n1[i].b;
38         sum2=0;
39         for(int j=0;j<num2;j++){
40             if(n2[j].a>price) break;
41             sum2+=n2[j].b;
42         }
43         if(ans_num<min(sum1,sum2)){
44             ans_num=min(sum1,sum2);
45              ans_price=price;
46          }
47     }
48 }
49 
50 int main()
51 {
52    //  freopen("in.txt","r",stdin);
53     num=1;
54     memset(flag,1,sizeof(flag));
55     while(cin>>n[num].s){
56         if(n[num].s=="buy"||n[num].s=="sell"){
57             scanf("%lf%lld",&n[num].a,&n[num].b);
58             num++;
59         }
60         else if(n[num].s=="cancel"){
61             scanf("%lld",&n[num].b);
62             num++;
63         }
64     }
65     for(int i=num-1;i>=1;i--)
66     {
67         if(n[i].s=="cancel"){
68             flag[n[i].b]=1-flag[n[i].b];
69         }
70     }
71     num1=0;num2=0;
72     for(int i=1;i<num;i++)
73     {
74         if(flag[i]){
75             if(n[i].s=="buy"){
76                 n1[num1].a=n[i].a;
77                 n1[num1++].b=n[i].b;
78             }
79             else  if(n[i].s=="sell"){
80                 n2[num2].a=n[i].a;
81                 n2[num2++].b=n[i].b;
82             }
83         }
84     }
85     sort(n1,n1+num1,cmp2);
86     sort(n2,n2+num2,cmp1);
87     slove();
88     printf("%.2lf %lld\n",ans_price,ans_num);
89     return 0;
90  }
问题描述
  雷雷承包了很多片麦田,为了灌溉这些麦田,雷雷在第一个麦田挖了一口很深的水井,所有的麦田都从这口井来引水灌溉。
  为了灌溉,雷雷需要建立一些水渠,以连接水井和麦田,雷雷也可以利用部分麦田作为“中转站”,利用水渠连接不同的麦田,这样只要一片麦田能被灌溉,则与其连接的麦田也能被灌溉。
  现在雷雷知道哪些麦田之间可以建设水渠和建设每个水渠所需要的费用(注意不是所有麦田之间都可以建立水渠)。请问灌溉所有麦田最少需要多少费用来修建水渠。
输入格式
  输入的第一行包含两个正整数n, m,分别表示麦田的片数和雷雷可以建立的水渠的数量。麦田使用1, 2, 3, ……依次标号。
  接下来m行,每行包含三个整数a i, b i, c i,表示第a i片麦田与第b i片麦田之间可以建立一条水渠,所需要的费用为c i
输出格式
  输出一行,包含一个整数,表示灌溉所有麦田所需要的最小费用。
样例输入
4 4
1 2 1
2 3 4
2 4 2
3 4 3
样例输出
6
样例说明
  建立以下三条水渠:麦田1与麦田2、麦田2与麦田4、麦田4与麦田3。
评测用例规模与约定
  前20%的评测用例满足:n≤5。
  前40%的评测用例满足:n≤20。
  前60%的评测用例满足:n≤100。
  所有评测用例都满足:1≤n≤1000,1≤m≤100,000,1≤ci≤10,000。

//最小生成数prim
#include<bits/stdc++.h>
using namespace std;
const int maxn=1007;
const int inf=0x3f3f3f3;
int n,m;
struct node
{
    int to,cost;
};
bool vis[maxn];
int d[maxn];
vector<node> G[maxn];
void init()
{
    for(int i=0;i<maxn;i++)
    {
        G[i].clear();
    }
}
int prim()
{
    int ans=0;
    for(int i=1;i<maxn;i++)
    {
        d[i]=inf;
        vis[i]=0;
    }
    d[1]=0;
    while(1){
        int v=-1;
        for(int i=1;i<=n;i++)
        {
            if(!vis[i]&&(v==-1||d[i]<d[v])) v=i;
        }
        if(v==-1) break;
        vis[v]=1;
        ans+=d[v];
        for(int i=0;i<G[v].size();i++)
        {
              if(vis[G[v][i].to]) continue;
              d[G[v][i].to]=min(d[G[v][i].to],G[v][i].cost);
        }
    }
    return ans;
}
int main()
{
    //freopen("in.txt","r",stdin);
     int a,b,c; node n1;
      while(~scanf("%d%d",&n,&m)){
        init();
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            n1.to=b;n1.cost=c;
            G[a].push_back(n1);
            n1.to=a;
            G[b].push_back(n1);
        }
        int ans=prim();
        printf("%d\n",ans);
      }
}

问题描述
  给定n个不同的整数,问这些数中有多少对整数,它们的值正好相差1。
输入格式
  输入的第一行包含一个整数n,表示给定整数的个数。
  第二行包含所给定的n个整数。
输出格式
  输出一个整数,表示值正好相差1的数对的个数。
样例输入
6
10 2 6 3 7 8
样例输出
3
样例说明
  值正好相差1的数对包括(2, 3), (6, 7), (7, 8)。
评测用例规模与约定
  1<=n<=1000,给定的整数为不超过10000的非负整数。

 1  #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     //freopen("in.txt","r",stdin);
 6     int ans=0;
 7     int num[10007];
 8     int n,a;
 9     while(~scanf("%d",&n)){
10         memset(num,0,sizeof(num));
11         for(int i=0;i<n;i++)
12         {
13             scanf("%d",&a);
14             num[a]++;
15         }
16     for(int i=1;i<=9999;i++)
17     {
18         ans+=min(num[i],num[i+1]);
19     }
20     cout<<ans<<endl;
21     }
22     return 0;
23  }
问题描述
  在一个定义了直角坐标系的纸上,画一个(x1,y1)到(x2,y2)的矩形指将横坐标范围从x1到x2,纵坐标范围从y1到y2之间的区域涂上颜色。
  下图给出了一个画了两个矩形的例子。第一个矩形是(1,1) 到(4, 4),用绿色和紫色表示。第二个矩形是(2, 3)到(6, 5),用蓝色和紫色表示。图中,一共有15个单位的面积被涂上颜色,其中紫色部分被涂了两次,但在计算面积时只计算一次。在实际的涂色过程中,所有的矩形 都涂成统一的颜色,图中显示不同颜色仅为说明方便。
给出所有要画的矩形,请问总共有多少个单位的面积被涂上颜色。
输入格式
  输入的第一行包含一个整数n,表示要画的矩形的个数。
  接下来n行,每行4个非负整数,分别表示要画的矩形的左下角的横坐标与纵坐标,以及右上角的横坐标与纵坐标。
输出格式
  输出一个整数,表示有多少个单位的面积被涂上颜色。
样例输入
2
1 1 4 4
2 3 6 5
样例输出
15
评测用例规模与约定
  1<=n<=100,0<=横坐标、纵坐标<=100。
#include<bits/stdc++.h>
using namespace std;
bool flag[107][107];
int n;
int x1,yy1,x2,y2;
void slove()
{
    for(int i=x1;i<x2;i++)
        for(int j=yy1;j<y2;j++)
         flag[i][j]=1;
}
int main()
{
 //     freopen("in.txt","r",stdin);
    while(~scanf("%d",&n)){
          memset(flag,0,sizeof(flag));
       for(int i=0;i<n;i++)
                {
                    scanf("%d%d%d%d",&x1,&yy1,&x2,&y2);
                     slove();
                }
            int ans=0;
        for(int i=0;i<=100;i++)
            for(int j=0;j<=100;j++)
        {
            if(flag[i][j]) ans++;
        }
        cout<<ans<<endl;
    }
    return 0;
}
问题描述
  给出一个字符串和多行文字,在这些文字中找到字符串出现的那些行。你的程序还需支持大小写敏感选项:当选项打开时,表示同一个字母的大写和小写看作不同的字符;当选项关闭时,表示同一个字母的大写和小写看作相同的字符。
输入格式
  输入的第一行包含一个字符串S,由大小写英文字母组成。
  第二行包含一个数字,表示大小写敏感的选项,当数字为0时表示大小写不敏感,当数字为1时表示大小写敏感。
  第三行包含一个整数n,表示给出的文字的行数。
  接下来n行,每行包含一个字符串,字符串由大小写英文字母组成,不含空格和其他字符。
输出格式
  输出多行,每行包含一个字符串,按出现的顺序依次给出那些包含了字符串S的行。
样例输入
Hello
1
5
HelloWorld
HiHiHelloHiHi
GrepIsAGreatTool
HELLO
HELLOisNOTHello
样例输出
HelloWorld
HiHiHelloHiHi
HELLOisNOTHello
样例说明
  在上面的样例中,第四个字符串虽然也是Hello,但是大小写不正确。如果将输入的第二行改为0,则第四个字符串应该输出。
评测用例规模与约定
  1<=n<=100,每个字符串的长度不超过100
#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include <iostream>
#include <algorithm>
#include <vector>
#include <functional>
#include <cctype>
using namespace std;
string s1,s2;
int n;
void solve(string &s)
{
    int l=s.size();
    for(int i=0;i<l;i++)
    {
        if(s[i]>='A'&&s[i]<='Z') s[i]=s[i]-'A'+'a';
    }
}
int main()
{
  // freopen("in.txt","r",stdin);
    int flag;
    while(cin>>s1){
        scanf("%d",&flag);
        if(flag){
             scanf("%d",&n);
             for(int i=0;i<n;i++)
             {
                 cin>>s2;
                 if(s2.find(s1)!= s2.npos) cout<<s2<<endl;
             }
        }
        else{
            solve(s1);
            scanf("%d",&n);
             for(int i=0;i<n;i++)
             {
                 cin>>s2;
                  string s3=s2;
                 solve(s2);

                 if(s2.find(s1) != s2.npos) cout<<s3<<endl;
             }
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值