Codeforces Round #283(Div.2) A,B,C,D,E 解题报告
来源:互联网 发布:软件测试linux 编辑:程序博客网 时间:2024/05/17 07:54
转载请注明出处,谢谢
http://blog.csdn.net/wyBluewind/article/details/47682783
codeforces 上写的题解 by Endagorion:http://codeforces.com/blog/entry/15208
写在前面:第一次写博客,也是第一次写题解,写的不好请各路高手指导。
A. Minimum Difficulty
题意:
简单题。
思路:
找一下挨着的差的最大值,然后间隔为2时最大的最小即可。详细见代码。
代码:
#include<iostream> #include<cmath> using namespace std; int n,d1,d2,ans; int a[1009]; int main() { while(cin >> n){ d1=d2=-1; for(int i=0; i<n; ++i) cin >> a[i]; for(int i=1; i<n; ++i) d1=max(a[i]-a[i-1],d1); ans=100000; for(int i=2; i<n; ++i){ d2 = max(a[i]-a[i-2],d1); ans=min(ans,d2); } cout << ans << endl; } return 0; }
B. Secret Combination
题目大意:
有一个n位的数字组合锁,锁上有两个按钮可以改变显示的数字。第一个按钮是将n位数字每一位都加一(9 会变成0),第二个按钮将所有位右移一位(最后一位变成第一位)。按下第一个按钮:579 会变成 680 , 再按下第二个按钮 680 会变成 068。
需要找到可以显示出的最小的数,前导零会被忽略。
思路:
肯定是前导0越多数越小。所以第一位一定是0,然后找出每一位在第一位且变成0时的显示的数字大小,然后比较即可。
代码:
#include<iostream> #include<string> #include<fstream> using namespace std; int n,len; string s,ans,temp; int main(){ // ifstream cin; // cin.open("in.txt"); while(cin >> n){ cin >> s; len =s.size(); temp = s + s; ans=s; for(int i=0; i<len; ++i){ int t = 10-(temp[i]-'0'); s=""; for(int j=i; j<i+len; ++j){ s += (char)(((temp[j]-'0')+t)%10 + '0'); } if(ans>s) ans = s; } cout << ans << endl; } return 0; }
C. Removing Columns
题目大意:
一个由小写英文字母组成的n×m的表格,你可以删除表格中的某一列。如果一个表格从上到下满足按字典序递增(可以相同),则它就是一个‘good table’
,问最少删除几列可以变成‘good table’
思路:
从简单的入手就一行行的比较,如果不满足要求就把这列标记为删除,注意这列删除了可能会影响前面比较完的结果,比如
aab
aba
aaa
第三行和第二行比较时,删除第二列之后会影响到第二行和第一行的比较结果。所以每次删除一列之后,都要从第一行重新比较。此时我们需要记录一下每一行和前一行在哪一列比较出的结果,每次从这个标记列开始比较就好了,不用每次都从第一列开始比较。最后统计一下删除的列就行了。
这个时间复杂度,因为最多有m次重新比较,每次比较的代价就是n×m的, 所以就是O(m×n×m)。[我也不知道对不对,有错误的话请告诉我,我改正,谢谢了]
代码:
#include<iostream> #include<fstream> #include<cstring> using namespace std; int n,m; bool is[105]; int flg[109]; char grid[105][105]; int main() { // ifstream cin; // cin.open("in.txt"); while(cin >> n >> m){ for(int i=0; i<n; ++i){ for(int j=0; j<m; ++j){ cin >> grid[i][j]; } } memset(is,true,sizeof(is)); memset(flg,0,sizeof(flg)); for(int i=1; i<n; ++i){ for(int j=flg[i]; j<m; ++j){ if(is[j]){ if(grid[i][j] < grid[i-1][j]){ is[j]=false; i=0; break; } else if(grid[i][j] == grid[i-1][j]){ flg[i]=j; } else{ flg[i]=j; break; } } } } int ans=0; for(int i=0; i<m; ++i) if(!is[i]) ans++; cout << ans << endl; } return 0; }
D. Tennis Game
题目大意:
Petya和Gena打乒乓球,一场比赛有很多局,每局有多次发球。每赢一次发球得1分,每局先赢t分的人赢了这局,下局重新记分,先赢s局的人赢得比赛。现在有一系列记录每次发球的胜者,但是不知道t和s,需要找出满足这个记录的所有t和s。
思路:
对于这种找满足要求的数的,我觉得就是枚举。直接枚举一定会超时,O(n^2)需要优化。
这题先枚举t,然后找满足的s,当然对于固定的t最多只有一个s与之对应。当一局结束后,向后找t个1和t个2,哪个先出现这局就是他赢了。可以利用二分查找来找t个1和t个2,这样就可以优化到O(nlogn)了(我之前用二分搜索实现的但是TLE了 >_< ,后来用了一个机智的方法用O(1)的时间代替了二分查找)。
注意几个问题:若1和2的个数都不满足t个,那么就说明不满足要求,还有赢最后一局的人一定是最后的赢家(之前在这wa了)。
代码:
#include<iostream> #include<cstring> #include<cstdio> #include<fstream> #include<utility> #include<algorithm> #include<vector> using namespace std; const int MAXN = 1000000; int n; int a[100009][2], pos[100009][2]; struct P{ int s; int t; }res[100009]; int num=0; bool cmp(const P &a1, const P &a2){ if(a1.s!=a2.s) return a1.s<a2.s; else return a1.t<a2.t; } int main() { // freopen("in.txt","r",stdin); while(scanf("%d",&n)!=EOF){ memset(a,0,sizeof(a)); for(int i=1,t; i<=n; ++i){ scanf("%d", &t); if(t==1){ a[i][0]=a[i-1][0]+1; a[i][1]=a[i-1][1]; pos[a[i][0]][0]=i; } else{ a[i][1]=a[i-1][1]+1; a[i][0]=a[i-1][0]; pos[a[i][1]][1]=i; } } int a1=0,a2=0; num=0; for(int i=1; i<=n; ++i){ int j=0; a1=a2=0; int last=-1; while(j<n){ if(a[j][0]+i <= a[n][0] && a[j][1]+i <= a[n][1]){ int k1 = pos[a[j][0]+i][0]; int k2 = pos[a[j][1]+i][1]; if(k1<k2) a1++,j=k1,last=1; else if(k2<k1) a2++,j=k2,last=2; else break; } else if(a[j][0]+i <= a[n][0] && a[j][1]+i > a[n][1]){ a1++,j=pos[a[j][0]+i][0];last=1; } else if(a[j][0]+i > a[n][0] && a[j][1]+i <= a[n][1]){ a2++,j=pos[a[j][1]+i][1]; last=2; } else break; } if(j==n && a1!=a2){ if(a1>a2 && last==1){ res[num].s=a1,res[num++].t=i; } if(a2>a1 && last==2){ res[num].s=a2, res[num++].t=i; } } } sort(res,res+num,cmp); int len = num; printf("%d\n",len); for(int i=0; i<len; ++i){ printf("%d %d\n",res[i].s,res[i].t); } } return 0; }
E. Distributing Parts
题目大意:
一个音乐播放器有m个单元,每个单元可以播放一首音乐,每个单元一个音量范围c,d,只可以播放该音量范围内的音乐,且最多可以放k首音乐,也可以不放任何音乐。现在有n首音乐,每首音乐也有个音量范围a,b,需要放到m个单元中。输出每首音乐用哪个单元播放。
思路:
这种一个范围需要放到另一个范围的题目,就是放到一起排序,然后处理。
首先按照最小音量升序排序,如果相同那么单元放在前面。然后从前到后一个个处理,如果碰到单元就放到集合里,如果碰到音乐就在现在的集合中找一个最小的d,此时c一定大于a,就是我们要找的播放单元,同时k需要减1。如果单元的k为0,就从集合中删除。这个集合可以用c++中的set维护(需要了解一下set的实现方式和用到的数据结构)。复杂度O((n+m)log(n+m));
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<set> using namespace std; struct Node{ int id,beg,en,flg,k; Node(){beg=0;en=0;flg=0;k=0;} inline bool operator < (const Node &a) const { if(beg != a.beg) return beg<a.beg; else return flg>a.flg; } }all[100009*2]; bool cmp1(const Node &a, const Node &b){ if(a.beg != b.beg) return a.beg<b.beg; else return a.flg>b.flg; } struct cmp2{ bool operator ()(const Node &a, const Node &b){ return a.en<b.en; } }; multiset<Node, cmp2> sets; multiset<Node, cmp2>::iterator it; int n,m; int ans[100009]; int used[100009]; int main() { // freopen("in.txt","r",stdin); while(cin >> n ){ for(int i=1,s,e; i<=n; ++i){ Node temp; cin >> s >> e; temp.beg = s; temp.en = e; temp.flg = 0; temp.id = i; all[i] = temp; } cin >> m; for(int i=1,s,e,k; i<=m; ++i){ Node temp; cin >> s >> e >> k; temp.beg = s; temp.en = e; temp.flg = 1; temp.k = k; temp.id = i; all[i+n] = temp; } sort(all+1, all+1+n+m, cmp1); bool flgs = true; memset(used,0,sizeof(used)); memset(ans,0,sizeof(ans)); for(int i=1; i<=n+m; ++i){ if(all[i].flg==1){ sets.insert(all[i]); } else{ it = sets.lower_bound(all[i]); if(it != sets.end()){ ans[all[i].id] = it->id; used[it->id]++; if(it->k == used[it->id] ){ sets.erase(it); } } else{ flgs=false; break; } } } if(flgs){ printf("YES\n%d", ans[1]); for(int i=2; i<=n; ++i) printf(" %d",ans[i]); printf("\n"); } else printf("NO\n"); } return 0; }
- Codeforces Round #283(Div.2) A,B,C,D,E 解题报告
- Codeforces Round #279 (Div. 2) 解题报告 A.B.C.D.E
- Codeforces Round #280 (Div. 2) 解题报告(A B C D E)
- Codeforces Round #280 (Div. 2) 解题报告 A.B.C.D.E.
- Codeforces Round #287 (Div. 2) 解题报告 A.B.C.D.E
- Codeforces Round #291 (Div. 2)解题报告A.B.C.D.E
- 解题报告:Codeforces Round #424 (Div. 2) A B C D E F
- Codeforces Round #283 (Div. 2) 解题报告(A B C)
- Codeforces Round #274 (Div. 2) 解题报告 (C D E)
- Codeforces Round #289 Div. 2 解题报告 A.B.C.E
- Codeforces Round #283 (Div. 1)解题报告A.B.C.
- Codeforces Round #283 (Div. 1)解题报告A.B.C.
- Codeforces Round #273 (Div. 2) 解题报告 (A B C D)
- Codeforces Round #277.5 (Div. 2) 解题报告(A B C D)
- Codeforces Round #279 (Div. 2) 解题报告(A B C D)
- Codeforces Round #281 (Div. 2) 解题报告(A B C D)
- Codeforces Round #281 (Div. 2) 解题报告 A.B.C.D.
- Codeforces Round #290 (Div. 2) 解题报告 A.B.C.D.
- ....
- 集合
- SAP Down Payment的设置和使用
- leetcode 两个有序数组合成
- NYOJ-1022合纵连横(并查集的删除操作)
- Codeforces Round #283(Div.2) A,B,C,D,E 解题报告
- 构建乘积数组
- CiscoVPNClient不支持WIN10
- OC关于NSDictionary和NSMutableDictionary方法的使用
- hdu 1588 Gauss Fibonacci
- Scala入门到精通——第二十七节 Scala操纵XML
- Android中的DVM和Java中的JVM的异同点?
- bzoj-2049 Cave 洞穴勘测
- CiTest测试