码迷,mamicode.com
首页 > 编程语言 > 详细

【2018.12.15】【考试总结】【模拟+逆序对+树状数组+贪心+multiset】爆零之旅

时间:2018-12-19 17:09:05      阅读:312      评论:0      收藏:0      [点我收藏+]

标签:set   close   有一个   就是   长度   为什么   模拟   hide   event   

这是我悲惨的接近爆零的一次考试,但是本蒟蒻不能放弃,还是要总结的QAQ

技术分享图片
答题卡
【题目背景】
八月是个悲惨的月份。先不谈炎热的天气,对于新生来说,八月意味着军训;
而对于高二高三的同学来说,八月意味着开学考试。而考试就意味着改卷,改卷
也就意味着答题卡。不幸的是,学校读答题卡的机器的评分软件坏了,wyx 就被
老师要求写一个评分的程序。
【问题描述】
软件需要读入学生的姓名、试题答案以及学生的答题卡信息。
学生姓名
学校的信息管理系统中存储了所有学生的姓名,一共 名学生。每个学生的
名字的组成只包含小写英文字母。如“a”,“hehe”,“nvshen”,“zouyuheng”,
“lixuexin”都是符合要求的学生姓名。
试题答案
开学考试一共 道选择题,均为不定项选择题。选项共四个,A、B、C 和D,
标准答案选项的数量为1~4个。不同题目的分值可能不同。每道题有两个分值,
设为满分和部分分,保证部分分不超过满分。只有当学生的答案与标准答案完全
一致时才能获得满分;当学生的答案不与标准答案完全一致,但是没有选择错误
选项,且选择了至少一个选项时才能获得部分分;对于其他情况,不得分。比如:
试题答案选项为ACD,只有当学生答案为ACD时才能获得满分,如果学生答案
为A、C、D、AC、AD或CD则可以获得部分分,其他情况均不得分。
答题卡
一个学生的答题卡占四行,可以视为四个字符串。四个字符串从左往右数的
第 个空为第 题A、B、C 和D 这四个选项的方框是否被填涂,X 代表填涂,.
代表未填涂。比如:
XX.
.X.
...
X..
则表示第一题选择AD,第二题选择AB,而第三题没有选择。
请你根据上述的信息,计算每位学生的得分,并将学生按照成绩排序输出。
对于成绩相同的学生,按照学姓名的字典序升序输出。输入数据保证不存在重名
的情况。
CCF 全国信息学奥林匹克联赛(NOIP2014)复赛提高组Day1 模拟训练答题卡
第 3 页共8 页
【输入格式】
输入数据第一行包含两个整数 和 ,分别表示学生数和试题数。
接下来 行,每行有一个字符串,表示第 位同学的姓名。
接下来 行,每行描述一道试题。第 行有两个非负整数和一个字符串,分
别为第 道试题的满分、部分分以及答案串。答案串仅含有”A”、”B”、”C”和”D”
四种字符,且每个字符最多出现一次。答案串中含有的字符即为该题的答案选项。
在最后一道试题答案之后包含一个空行。
接下来 份答题卡,每份四行,按照读入顺序描述每一位学生的答题卡。两
份答题卡之间用一个空行隔开。
【输出格式】
输出一共 行,按照问题描述中排序的顺序输出 位学生的信息。每行首先
输出该学生的姓名,然后输出一个空格,再输出这位同学的成绩。
【样例输入】
3 4
zouyuheng
lixuexin
wangyingxu
10 1 ABCD
10 10 C
5 0 CD
10 5 ABD
X..X
X..X
XXX.
X.XX
X..X
X..X
XXX.
X.XX
XXX.
.XX.
...X
.X..
CCF 全国信息学奥林匹克联赛(NOIP2014)复赛提高组Day1 模拟训练答题卡
第 4 页共8 页
【样例输出】
lixuexin 35
zouyuheng 35
wangyingxu 1
【样例说明】
在样例中,zouyuheng与lixuexin均获得满分,但由于lixuexin的字典
序更小,因此她排在他前面。而wangyingxu只有第一题部分正确,第二三四题
均错误,因此他的得分只有第一题的部分分1 分。
【数据规模与约定】
对于80%的数据,所有试题的答案选项只有一个,答题卡上每道题选择的选
项也只有一个且不存在两位同学得分相同的情况。
对于100%的数据, , ≤ 100,所有人的姓名长度不超过100
T1

 这道题呢其实就是个模拟,但是本蒟蒻挂了。。。导致整场考试几乎没分

怎么错的呢,没有把名字和分数打成结构体,排完分数最后直接把名字输出了,肯定是错的。。。。

然后改了两分钟八十了,为什么还有二十分挂了?

首先我的判分方式有问题,一旦这个人全都没涂,我给的还是满分,所以一个辅助变量解决,

所以思考一定要周全!!

然后呢还有一个事,就是题里要求升序输出,那么怎么升序呢

字典序是什么,就是字典里的顺序比如AB>ABC,AD>AEF

所以比较就是一位位往下扫,发现第一个不相等的决定他们两个之间的大小关系

就是这样(字典序和字符串长短没有半毛钱关系

1 for(int i=1;i<=strlen(a.name+1);i++)
2 {
3     if(a.name[i]>b.name[i])return 0;
4     else if(a.name[i]<b.name[i])return 1;
5 }
6 return 1;

 T1代码

技术分享图片
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #define _ 0
 5 using namespace std;
 6 int n,m;
 7 int man[150],part[150];
 8 struct node{int score;char name[150];}nd[150];
 9 bool operator<(node a,node b){
10     if(a.score==b.score)
11     {
12         for(int i=1;i<=strlen(a.name+1);i++)
13         {
14             if(a.name[i]>b.name[i])return 0;
15             else if(a.name[i]<b.name[i])return 1;
16         }
17         return 1;
18     }
19     return a.score>b.score;
20 }
21 bool an[150][5];
22 char ans[150][5],work[5][150];
23 int main()
24 {
25     freopen("sheet.in","r",stdin);
26     freopen("sheet.out","w",stdout);
27     scanf("%d%d",&n,&m);
28     for(int i=1;i<=n;i++)scanf("%s",nd[i].name+1);
29     for(int i=1;i<=m;i++)
30     {
31         scanf("%d%d%s",&man[i],&part[i],ans[i]+1);
32         for(int j=1;j<=strlen(ans[i]+1);j++)
33         {
34             if(ans[i][j]==A)an[i][1]=1;
35             else if(ans[i][j]==B)an[i][2]=1;
36             else if(ans[i][j]==C)an[i][3]=1;
37             else if(ans[i][j]==D)an[i][4]=1;
38         }
39     }
40     for(int st=1;st<=n;st++)
41     {
42         for(int i=1;i<=4;i++)
43         {
44             scanf("%s",work[i]+1);
45         }
46         for(int q=1;q<=m;q++)
47         {
48             int defen=2,tule=0;
49             for(int k=1;k<=4;k++)
50             {
51                 if(work[k][q]==X)
52                 {
53                     tule=1;
54                     if(an[q][k]==0){defen=0;break;}
55                 }
56                 else
57                 {
58                     if(an[q][k]==1)defen=1;
59                 }
60             }
61             if(tule==0)nd[st].score+=0;
62             else if(defen==0)nd[st].score+=0;
63             else if(defen==1)nd[st].score+=part[q];
64             else if(defen==2)nd[st].score+=man[q];
65         }
66     }
67     sort(nd+1,nd+n+1);
68     for(int i=1;i<=n;i++)
69     {
70         for(int k=1;k<=strlen(nd[i].name+1);k++)printf("%c",nd[i].name[k]);
71         printf(" %d\n",nd[i].score);
72     }
73     fclose(stdin);
74     fclose(stdout);
75     return ~~(0^_^0);
76 }
View Code

 

然后我们看T2

技术分享图片
秘密邮件
【问题描述】
Sharon 收到了一封来自外星球的秘密邮件。邮件由n 个大写英文字母组成,
不巧的是Sharon 收到邮件以后一不小心打乱了原来的字母顺序。但是聪明的
Sharon 记住了原邮件的完整内容,现在她每次可以选择打乱后的邮件中相邻的
两个字母进行交换,问最少交换多少次能够将打乱的邮件恢复成原邮件。
【输入格式】
第一行一个整数n 表示邮件的长度。
第二行一个长度为n 的只包含大写字母的字符串表示打乱后的邮件。
第三行一个长度为n 的只包含大写字母的字符串表示原邮件。
为保证打乱后的邮件可以恢复成原邮件,所有的测试数据满足任意一种大写
字母在两封邮件中的出现次数相同。
【输出格式】
共一行包含一个整数,表示最少的交换次数。
【样例输入】
4
ABCD
DBCA
【样例输出】
5
【样例说明】
第一次交换第一个和第二个字母得到BACD;
第二次交换第二个和第三个字母得到BCAD;
第三次交换第三个和第四个字母得到BCDA;
第四次交换第二个和第三个字母得到BDCA;
第五次交换第一个和第二个字母得到DBCA。
CCF 全国信息学奥林匹克联赛(NOIP2014)复赛提高组Day1 模拟训练秘密邮件
第 6 页共8 页
【数据规模与约定】
所有测试点的数据规模如下:
测试点编号n 的规模约定
1 n = 2
保证每种字母最
多只出现一次
2 n = 10
3 n = 15
4 n = 26
5 n = 5,000
保证最多只出现
两种字母6 n = 1,000,000
7 n = 1,000,000
8 n = 5,000
9 n = 1,000,000 /
10 n = 1,000,000
T2

 这道题本蒟蒻看了五分钟看出逆序对,然后呢,然后呢,然后挂了

逆序对怎么求?树状数组,这个木有问题

然后这道题对于重复字母有一些处理方法

这是一个小贪心,我们维护26个桶,把编号塞进里面

然后从桶底开始作为要求逆序对的数列,就OK

但是本蒟蒻卡了一些玄学的东西,不知道为什么就WA了,代码准度还是不够

 

 T2代码

技术分享图片
 1 #include<cstdio>
 2 #include<cstring>
 3 #define N 1000011
 4 using namespace std;
 5 int n,bucket[30][N],cnt[30],ac[N],p[30],tree[N];
 6 long long ans;
 7 char be[N],af[N];
 8 int lowbit(int a)
 9 {
10     return a&(-a);
11 }
12 void add(int pos,int val)
13 {
14     for(int i=pos;i;i-=lowbit(i))
15     {
16         tree[i]+=val;
17     }
18 }
19 int getsum(int pos)
20 {
21     int t = 0;
22     for(int i = pos;i<=n;i+=lowbit(i))
23     {
24         t+=tree[i];
25     }
26     return t;
27 }
28 int main()
29 {
30     freopen("letter.in","r",stdin);
31     freopen("letter.out","w",stdout);
32     scanf("%d",&n);
33     scanf("%s",be+1);
34     scanf("%s",af+1);
35     for(int i=1;i<=n;i++)
36     {
37         int now=be[i]-A+1;
38         cnt[now]++;
39         bucket[now][cnt[now]]=i;
40     }
41     for(int i=1;i<=n;i++)
42     {
43         int now=af[i]-A+1;
44         p[now]++;
45         ac[i]=bucket[now][p[now]];
46     }
47 //    for(int i=1;i<=n;i++)printf("%d ",ac[i]);
48     for(int i = 1;i<=n;i++)
49     {
50         ans+=getsum(ac[i]);
51         add(ac[i],1);            
52     }
53     printf("%I64d\n",ans);
54     return 0;
55 }
View Code

 

 

我们看T3

技术分享图片
庐州月
【引子】
桥上的恋人入对出双
桥边红药叹夜太漫长
月也摇晃 人也彷徨
乌蓬里传来了一曲离殇
庐州月光 洒在心上
月下的你不复当年模样
太多的伤 难诉衷肠
叹一句当时只道是寻常
庐州月光 梨花雨凉
如今的你又在谁的身旁
家乡月光 深深烙在我心上
却流不出当年泪光 ——Vae《庐州月》
【问题描述】
小 G 是出生在庐州的一位同学,当他高中毕业后,回到了自己的家乡。然
而家乡已不复当年模样,在高中表现优秀的小G 决定承担起家乡的一件重任,
那就是修理已经破烂不堪的石桥。
家乡中共有n 个石桥等待修理,对于第i 个石桥,我们定义两个参数pi,vi,
其中pi表示修理石桥的最小花费值,vi表示石桥需要的最小美化需求度。今天,
小G 已了解到修理厂共有m 种不同的修理原料,对于第i 种原料,可以对任意
一个石桥的美化度增加di,当然这也需要花费hi的费用。由于发货场的修理原料
有限,对于任意一种修理原料,只有一件,也就是说小G 只能选择购买和不购
买,对于第i 种修理材料能成功修理第j 个石桥的条件是:当且仅当hi ≥ pj,di ≥
vj。现在,已知这n 个石桥修理的最小花费值,最小美化需求度,以及m 种修理
原料的费用,可对石桥增加的美化度值,请你帮助小G完成这个修理任务。
【输入格式】
第一行包括两个正整数,n,m。
接下来n 行中,每行包括两个正整数pi,vi。
接下来m行中,每行包括两个正整数hi,di。
【输出格式】
只有一个整数,为最小修理花费。如果无法完成修理任务,则输出一个整数
-1。
CCF 全国信息学奥林匹克联赛(NOIP2014)复赛提高组Day1 模拟训练庐州月
第 8 页共8 页
【样例输入】
2 3
2 3
5 9
3 10
3 5
6 11
【样例输出】
9
【样例说明】
其中一种可行的方案是:使用第1 种材料,修理第1 个石桥,使用第3 种材
料,修理第2 个石桥,最小修理花费为3 + 6 = 9。
【数据规模与约定】
所有测试点的数据规模如下:
测试点编号n 的规模m的规模
1 n ≤ 10 m ≤ 10
2 n ≤ 10 m ≤ 10
3 n ≤ 10 m ≤ 10
4 n ≤ 10 m ≤ 10
5 n ≤ 20 m ≤ 20
6 n ≤ 30 m ≤ 30
7 n ≤ 40 m ≤ 40
8 n ≤ 50 m ≤ 50
9 n ≤ 500 m ≤ 500
10 n ≤ 1,000 m ≤ 1,000
11 n ≤ 1,500 m ≤ 1,500
12 n ≤ 2,000 m ≤ 2,000
13 n ≤ 20,000 m ≤ 20,000
14 n ≤ 30,000 m ≤ 30,000
15 n ≤ 40,000 m ≤ 40,000
16 n ≤ 60,000 m ≤ 60,000
17 n ≤ 70,000 m ≤ 70,000
18 n ≤ 80,000 m ≤ 80,000
19 n ≤ 100,000 m ≤ 100,000
20 n ≤ 100,000 m ≤ 100,000
对于全部测试数据满足1 ≤ n,m ≤ 100,0001 ≤ pi,vi,di,hi ≤ 109
T3

 吐槽下出题人,竟然还写了一首诗。。

这道题呢,我考试时候用的stl,重载<号,死亡ing,把判断-1删除之后就得了60。。。

这道题的思路是什么呢,为什么会是O(能过)??

这道题的思路就是,先把需求和材料按美观度排序

然后外层枚举n,内层枚举m;

但是内层很巧妙,每次都把美观度大于当前需求的花费insert进set,然后lower_bound(得出第一个大于需要的花费)

这就是巧妙之处了,set里是不清空的,而且我已经预先把美观度排序了,所以set里的都是满足条件的,每次选第一个大于当前花费的就OK了

还有第二个巧妙之处,它的复杂度不是O(nm)的原因呢?内层的枚举不是1~n,是p~n,p每次insert都++,这样肯定小于O(nm)最坏情况为O(nlogm)

这道题之前做过原题但是我忘了。。。

T3代码

技术分享图片
 1 #include<cstdio>
 2 #include<set>
 3 #include<algorithm>
 4 #define N 100011
 5 using namespace std;
 6 int n,m,p=1;
 7 long long ans;
 8 struct node{int a,b;}n1[N],n2[N];
 9 bool cmp(node a,node b)
10     {return a.b>b.b;}
11 multiset<int>mm;
12 int main()
13 {
14     freopen("moon.in","r",stdin);
15     freopen("moon.out","w",stdout);
16     scanf("%d%d",&n,&m);
17     for(int i=1;i<=n;i++)
18         scanf("%d%d",&n1[i].a,&n1[i].b);
19     for(int i=1;i<=m;i++)
20         scanf("%d%d",&n2[i].a,&n2[i].b);
21     sort(n1+1,n1+n+1,cmp);
22     sort(n2+1,n2+m+1,cmp);
23     for(int i=1;i<=n;i++)
24     {
25         for(int j=p;j<=m;j++)
26         {
27             if(n2[j].b>=n1[i].b)
28             {
29                 mm.insert(n2[j].a);
30                 p++;
31             }else break;
32         }
33         multiset<int>::iterator it=mm.lower_bound(n1[i].a);
34         ans+=(long long)(*it);
35         mm.erase(it);
36     }
37     printf("%I64d",ans);
38     return 0;
39 }
View Code

 革命尚未成功,本蒟蒻还需努力QAQ

【2018.12.15】【考试总结】【模拟+逆序对+树状数组+贪心+multiset】爆零之旅

标签:set   close   有一个   就是   长度   为什么   模拟   hide   event   

原文地址:https://www.cnblogs.com/Qin-Wei-Kai/p/10143983.html

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