Codeforces Round #274 (Div. 2) 解题报告 (C D E)

来源:互联网 发布:网络免费群发短信 编辑:程序博客网 时间:2024/04/30 00:28

C. Exams


        思路:贪心。按考试时间排个序,优先排ai,若相等排bi。然后从头到尾扫一遍,得出最小值。

#include <iostream>       #include <stdio.h>       #include <cmath>       #include <algorithm>       #include <iomanip>       #include <cstdlib>       #include <string>       #include <string.h>       #include <vector>       #include <queue>       #include <stack>       #include <map>     #include <set>     #include <ctype.h>       #include <sstream>   #define INF 1000000000   #define ll long long   #define min3(a,b,c) min(a,min(b,c))#define max3(a,b,c) max(a,max(b,c))     using namespace std;struct ex{int a;int b;};ex e[5050];bool cmp(ex a,ex b){if(a.a!=b.a){return a.a<b.a;}return a.b<b.b;}int main(){int n;while(cin>>n){for(int i=1;i<=n;i++){cin>>e[i].a>>e[i].b;}sort(e+1,e+n+1,cmp);int ans=0;for(int i=1;i<=n;i++){int _min=min(e[i].a,e[i].b);int _max=max(e[i].a,e[i].b);if(_min>=ans){ans=_min;}else{ans=_max;}}cout<<ans<<endl;}return 0;}



D. Long Jumps


        思路:二分搜索/平衡搜索树(直接用set)。把尺子的每个刻度放到集合里,对每个刻度ai,查找ai+x和ai+y是否存在。如果不存在,测试是否能只添加一个刻度解决,如果不能,直接添加两个刻度。

        具体地说,如果原来就存在ai+x和ai+y中的一个,直接添加y/x就可以。如果都不存在,则需要测试ai±x±y是否存在。此题有坑:注意加的刻度不要溢出尺子的范围。


#include <iostream>       #include <stdio.h>       #include <cmath>       #include <algorithm>       #include <iomanip>       #include <cstdlib>       #include <string>       #include <string.h>       #include <vector>       #include <queue>       #include <stack>       #include <map>     #include <set>     #include <ctype.h>       #include <sstream>   #define INF 1000000000   #define ll long long   #define min3(a,b,c) min(a,min(b,c))#define max3(a,b,c) max(a,max(b,c))     using namespace std;int main(){ll n,l,x,y;set<ll> Set;while(cin>>n>>l>>x>>y){for(int i=1;i<=n;++i){ll t;scanf("%I64d",&t);Set.insert(t);}bool checkx=0;bool checky=0;for(set<ll>::iterator it=Set.begin();it!=Set.end();it++){if( Set.find(*it+x)!=Set.end() ){checkx=1;}if( Set.find(*it+y)!=Set.end() ){checky=1;}if(checkx&&checky){break;}}if(checkx&&checky){cout<<0<<endl;break;}if(checkx){cout<<1<<endl;cout<<y<<endl;break;}if(checky){cout<<1<<endl;cout<<x<<endl;break;}bool find=0;ll ans=0;for(set<ll>::iterator it=Set.begin();it!=Set.end();it++){if( (*it+x<=l)&&Set.find(*it+x+y)!=Set.end() ){find=1;ans=*it+x;break;}if( (*it+x<=l)&&Set.find(*it+x-y)!=Set.end() ){find=1;ans=*it+x;break;}if( (*it-x>=0)&&Set.find(*it-x+y)!=Set.end() ){find=1;ans=*it-x;break;}if( (*it-x>=0)&&Set.find(*it-x-y)!=Set.end() ){find=1;ans=*it-x;break;}}if(find){cout<<1<<endl;cout<<ans<<endl;break;}cout<<2<<endl;cout<<x<<" "<<y<<endl;}return 0;}


E. Riding in a Lift


        思路:DP(滚动数组)。dp(i,j)表示第 imod2 次转移后,走到j层有多少种方法。

        DP是很容易想到的,但是也很容易认为转移的复杂度是O(n)而放弃这个想法。其实转移的复杂度可以看成是O(1),这就需要一些小技巧。在状态转移的时候需要求区间和,我们可以先求一遍最大区间的和,边转移边维护区间的范围。

#include <iostream>       #include <stdio.h>       #include <cmath>       #include <algorithm>       #include <iomanip>       #include <cstdlib>       #include <string>       #include <string.h>       #include <vector>       #include <queue>       #include <stack>       #include <map>     #include <set>     #include <ctype.h>       #include <sstream>   #define INF 1000000000   #define ll long long   #define min3(a,b,c) min(a,min(b,c))#define max3(a,b,c) max(a,max(b,c))     using namespace std;const int mod=1E9+7;int n,a,b,k;int dp[2][5010];int main(){while(cin>>n>>a>>b>>k){if(a>b){a=1+(n-a);b=1+(n-b);}dp[0][a]=1;for(int i=1;i<=k;i++){for(int j=j;j<=b-1;j++)dp[i%2][j]=0;int sum=0;for(int j=1;j<=b-1;j++){sum+=dp[(i-1)%2][j];sum%=mod;}int test=b-1;for(int j=b-1;j>=1;j--){sum-=dp[(i-1)%2][j];sum+=mod;sum%=mod;dp[i%2][j]=sum;sum+=dp[(i-1)%2][j];sum%=mod;if(b-test<=test-(j-1) ){//测试是否需要缩小区间if(test!=(j-1) ){sum-=dp[(i-1)%2][test];sum+=mod;sum%=mod;test--;}}}}int ans=0;for(int i=1;i<b;i++){ans+=dp[k%2][i];ans%=mod;}cout<<ans<<endl;}return 0;}








0 0
原创粉丝点击