链接: http://2050.acmclub.cn/contests/contest_show.php?cid=3
7题,排名52,个人感觉还不错^_^
A-开场白
#include<bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int t;cin>>t;
while(t--){
string x;cin>>x;
while(x.length()>=4){
if(x.substr(0,4)=="2050"){
x.erase(0,4);
}
else break;
}
if(x=="")printf("Yes\n");
else printf("No\n");
}
}
B-时间间隔
因为要模100,所以小时是没有用的(60*60%100=0),直接算当前离整点的时间即可
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
int ct[1009];
int sum[1009];
int main(){
//ios::sync_with_stdio(false);
//cin.tie(0);
int t;
cin>>t;
while(t--){
int y,m,d,h,mm,s;
scanf("%d-%d-%d %d:%d:%d",&y,&m,&d,&h,&mm,&s);
printf("%d\n",(60*60-mm*60-s)%100);
}
return 0;
}
C-分宿舍
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
const int maxn=5009;
LL dp[maxn],a[5];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--){
LL n,m,k,b,c;
cin>>n>>m>>k>>a[2]>>a[3]>>c;
rep(i,1,5000)
dp[i]=1e18;
dp[0]=0;
dp[1]=min(a[2],a[3]);
dp[2]=min(2*a[2],a[3]);
rep(i,2,5000){
rep(j,2,3){
if(i<j)
continue;
if(dp[i-j]==1e18)
continue;
dp[i]=min(dp[i],dp[i-j]+a[j]);
}
}
for(int i=4999;i>=1;i--)
dp[i]=min(dp[i],dp[i+1]);
LL ans=1e18;
for(LL i=0;i<=k;i++){
ans=min(ans,dp[n+i]+dp[m+i]+(k-i)*c);
}
cout<<ans<<endl;
}
return 0;
}
D-PASS
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
int ct[1009];
int sum[1009];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int t;cin>>t;
while(t--){
int n,m,k;
cin>>n>>m>>k;
rep(i,1,m)ct[i]=sum[i]=0;
rep(i,1,n){
int tmp;cin>>tmp;sum[tmp]++;
if(i<=n/2)ct[tmp]++;
}
int ans=0;
rep(i,1,m){
int kk=sum[i]/k;
kk=min(kk,ct[i]);
ans+=kk;
}
cout<<ans<<endl;
}
}
E-球赛
dp[i][j][k]表示到了点i,j个A,k个B的最大比赛数。因为11-10和10-9是一样的,所以状态数只有11*11
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define repp(i,b,a) for(int i=b;i>=a;i--)
#define LL long long
int dp[10009][15][15];
char x[10009];
int main(){
//ios::sync_with_stdio(false);
//cin.tie(0);
int t;
cin>>t;
while(t--){
memset(dp,0xc0,sizeof dp);
scanf("%s",x+1);
dp[0][0][0]=0;
int len=strlen(x+1);
int jj,kk;
rep(i,1,len){
rep(j,0,10){
rep(k,0,10){
if(dp[i-1][j][k]<0)continue;
if(x[i]=='A')
jj=j+1,kk=k;
else if(x[i]=='B')
jj=j,kk=k+1;
else
jj=j,kk=k+1;
if(jj<11&&kk<11){
dp[i][jj][kk]=max(dp[i][jj][kk],dp[i-1][j][k]);
}
else if(jj==11){
if(kk<10){
dp[i][0][0]=max(dp[i][0][0],dp[i-1][j][k]+1);
}
else {
dp[i][jj-1][kk-1]=max(dp[i][jj-1][kk-1],dp[i-1][j][k]);
}
}
else if(kk==11){
if(jj<10){
dp[i][0][0]=max(dp[i][0][0],dp[i-1][j][k]+1);
}
else {
dp[i][jj-1][kk-1]=max(dp[i][jj-1][kk-1],dp[i-1][j][k]);
}
}
if(x[i]=='?'){
jj=j+1,kk=k;
if(jj<11&&kk<11){
dp[i][jj][kk]=max(dp[i][jj][kk],dp[i-1][j][k]);
}
else if(jj==11){
if(kk<10){
dp[i][0][0]=max(dp[i][0][0],dp[i-1][j][k]+1);
}
else {
dp[i][jj-1][kk-1]=max(dp[i][jj-1][kk-1],dp[i-1][j][k]);
}
}
else if(kk==11){
if(jj<10){
dp[i][0][0]=max(dp[i][0][0],dp[i-1][j][k]+1);
}
else {
dp[i][jj-1][kk-1]=max(dp[i][jj-1][kk-1],dp[i-1][j][k]);
}
}
}
}
}
}
int ans=0;
rep(i,0,10){
rep(j,0,10){
ans=max(ans,dp[len][i][j]);
}
}
printf("%d\n",ans);
}
return 0;
}
F-冰水挑战
dp[i][j]表示到了点i,完成j个的最大体力。注意要longlong
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define repp(i,b,a) for(int i=b;i>=a;i--)
#define LL long long
LL dp[1009][1009];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--){
memset(dp,0xc0,sizeof(dp));
LL n,cc;cin>>n>>cc;
dp[0][0]=cc;
rep(i,1,n){
LL a,b,c;cin>>a>>b>>c;
rep(j,0,i-1){
if(dp[i-1][j]<=0)continue;
dp[i][j]=max(dp[i][j],dp[i-1][j]+c);
if(min(dp[i-1][j],b)-a>0){
dp[i][j+1]=max(dp[i][j+1],min(dp[i-1][j],b)-a+c);
}
}
}
int ans=0;
repp(i,n,1){
if(dp[n][i]>0){
ans=i;break;
}
}
cout<<ans<<endl;
}
return 0;
}
G-大厦
先将第一种排好,再一条一条插入第二种(从上到下)。
对于当前线,算出于其交与矩形内的左右边界,对边界内的段的累加器+1。我们再计算出以当前线为底(直线的左上方)有多少个矩形。转换为下图:
显然答案=
,上图的答案为(2+3+4+3+3+2)+(min(2,3)…)+(min(2,3,4)…)…即任意区间的min值之和。
这个可以用单调栈来做,用sum来维护栈内所有值之和。下面是栈的维护过程,具体看代码:
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define repp(i,b,a) for(int i=b;i>=a;i--)
#define LL long long
const LL mod=1e9+7;
int a[1009],b[1009],ct[1009];int w,h,n,m;
bool in(double x,double y){
if(x<0||y<0||x>w*1.0||y>h*1.0)return 0;
return 1;
}
int sta[1009],top;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--){
rep(i,1,1000)ct[i]=-1;
cin>>w>>h>>n>>m;
rep(i,1,n)cin>>a[i];
rep(i,1,m)cin>>b[i];
sort(a+1,a+1+n);
sort(b+1,b+1+m);
double x,y;
LL Ans=0;
rep(i,1,m){
int l=-1,r=-1;
rep(j,1,n){
x=(a[j]+b[i])*1.0/2;
y=x-b[i]*1.0;
if(in(x,y)){l=j;break;}
}
if(l==-1)continue;
repp(j,n,1){
x=(a[j]+b[i])*1.0/2;
y=x-b[i]*1.0;
if(in(x,y)){r=j;break;}
}
rep(j,l,r-1){
ct[j]++;
}
//单调栈
top=0;
LL sum=0;
rep(j,l,r-1){
while(top&&ct[j]<=ct[sta[top]]){
if(top==1){
sum=0;
}
else{
sum=((sum-(LL)ct[sta[top]]*(LL)(sta[top]-sta[top-1]))%mod+mod)%mod;
}
top--;
}
sta[++top]=j;
if(top==1)
sum=(LL)ct[j]*(LL)(j-l+1)%mod;
else
sum=(sum+ct[j]*(LL)(j-sta[top-1]))%mod;
Ans=(Ans+sum)%mod;
}
}
cout<<Ans<<endl;
}
return 0;
}