Codeforces 5



A. Chat Server's Outgoing Traffic

        题目地址:http://codeforces.com/contest/5/problem/A

        题目大意:见原题。

        算法讨论:用STL的string和map维护。

        Code:

#include <cstdio>
#include <cstring>
#include <set>
#include <string>

using namespace std;

int ans,pos;
char s[1000];
set<string> Set;

int main(){
	while (fgets(s,1000,stdin)!=NULL){
		int l=strlen(s);
		while (s[l-1]=='\n' || s[l-1]=='\r') l--;
		s[l]='\0';
		if (s[0]=='+') Set.insert(string(s+1));
		else if (s[0]=='-') Set.erase(string(s+1));
		else{
			for (int i=0;i<l;++i)
			    if (s[i]==':') pos=i;
			ans+=Set.size()*(l-pos-1);
		}
	}
	printf("%d\n",ans);
	return 0;
}


B. Center Alignment

        题目地址:http://codeforces.com/contest/5/problem/B

        题目大意:见原题。

        算法讨论:比较坑的一点是当左右空格数之和为奇数时,第一次空格左少右多,第二次左多右少,第三次左少右多,以此类推。

        Code:

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>

using namespace std;

bool f;
int n,len;
char s[10000];
string str[10000];

int main(){
	#ifndef ONLINE_JUDGE
	freopen("B.in","r",stdin);
	freopen("B.out","w",stdout);
	#endif
	while (fgets(s,10000,stdin)!=NULL){
		int l=strlen(s);
		while (s[l-1]=='\n' || s[l-1]=='\r') l--;
		s[l]='\0';
		str[++n]=string(s);
		len=max(len,l);
	}
	for (int i=1;i<=len+2;++i) printf("*");
	puts("");
	for (int i=1;i<=n;++i){
		printf("*");
		if ((len-str[i].length())%2==0){
			for (int j=1;j<=(len-str[i].length())/2;++j) printf(" ");
			cout<<str[i];
			for (int j=1;j<=(len-str[i].length())/2;++j) printf(" ");
		}
		else if (!f){
			for (int j=1;j<=(len-str[i].length())/2;++j) printf(" ");
			cout<<str[i];
			for (int j=1;j<=(len-str[i].length())/2+1;++j) printf(" ");
			f=1;
		}
		else{
			for (int j=1;j<=(len-str[i].length())/2+1;++j) printf(" ");
			cout<<str[i];
			for (int j=1;j<=(len-str[i].length())/2;++j) printf(" ");
			f=0;
		}
		puts("*");
	}
	for (int i=1;i<=len+2;++i) printf("*");
	puts("");
	return 0;
}


C. Longest Regular Bracket Sequence

        题目地址:http://codeforces.com/contest/5/problem/C

        题目大意:给出一个括号序列,问最长的合法子串的长度是多少,并且这样的最长子串有多少个。

        算法讨论:dp思想,f[i]表示到i为止的最长合法子串的长度。用栈维护即可。

        Code:

#include <cstdio>
#include <cstring>
#include <stack>

#define N 1000000

using namespace std;

char s[N+10];
int l,ans,num,f[N+10];
stack<int> st;

int main(){
	scanf("%s",s);
	l=strlen(s);
	for (int i=0;i<l;++i)
		if (s[i]=='(') st.push(i+1);
		else if (!st.empty()){
			int t=st.top();
			st.pop();
			f[i+1]=f[t-1]+i+1-t+1;
		}
	for (int i=1;i<=l;++i)
		if (f[i]>ans) ans=f[i],num=1;
		else if (f[i]==ans) num++;
	if (!ans) printf("0 1\n");
	else printf("%d %d\n",ans,num);
	return 0;
}


D. Follow Traffic Rules

        题目地址:http://codeforces.com/contest/5/problem/D

        题目大意:一条长l的路,距起点距离为d的点的限速为w,全程限速为v,最大加速度为a,问起点到终点的最短时间。

        算法讨论:物理必修一,分类讨论。

        Code:

#include <cstdio>
#include <cmath>

using namespace std;

double a,v,l,d,w,vmax,t1,t2,s,s1,s2;

int main(){
	scanf("%lf%lf%lf%lf%lf",&a,&v,&l,&d,&w);
	if (w>v) w=v;
	if (w*w/2/a>=d){
		if (v*v/a/2>l) printf("%.9lf\n",sqrt(2*l/a));
		else printf("%.9lf\n",v/a+(l-v*v/2/a)/v);
		return 0;
	}
	double vmax=sqrt(a*d+w*w/2);
	if (vmax<=v){
		t1=vmax/a+(vmax-w)/a;
		s=(v*v-w*w)/2/a;
		if (s<=l-d){
			t2=(v-w)/a+(l-d-s)/v;
			printf("%.9lf\n",t1+t2);
		}
		else printf("%.9lf\n",t1+(-2*w+sqrt(4*w*w-8*a*(d-l)))/2/a);
		return 0;
	}
	s1=d-(2*v*v-w*w)/2/a;
	t1=s1/v+v/a+(v-w)/a;
	s2=(v*v-w*w)/2/a;
	if (s2<=l-d){
		t2=(v-w)/a+(l-d-s2)/v;
		printf("%.9lf\n",t1+t2);
	}
	else printf("%.9lf\n",t1+(-2*w+sqrt(4*w*w-8*a*(d-l)))/2/a);
	return 0;
}


E. Bindian Signalizing

        题目地址:http://codeforces.com/contest/5/problem/E

        题目大意:一个圆上有n个点,每个点有一个高度,两个点能相互看见当且仅当两个点之间的点都不高于这2个点,问有几对点能相互看见。

        算法讨论:

                先找到最高的那个点,以这个点将圆拉成链,可以证明这样操作后的答案不变。

                记录一个点的左边第一个比它高的点l[i],右边第一个比它高的点r[i]和i到r[i]之间高度等于i的点数c[i]。

                其中r[i]和c[i]的求解可用dp思想。

        Code:

#include <cstdio>

using namespace std;

#define N 1000000

int n,cnt,Max,which,h[N+10],a[N+10],l[N+10],r[N+10],c[N+10];
long long ans;

int main(){
	scanf("%d",&n);
	for (int i=1;i<=n;++i){
		scanf("%d",&h[i]);
		if (h[i]>Max) Max=h[i],which=i;
	}
	a[1]=h[which];
	cnt=1;
	for (int i=which+1;i<=n;++i) a[++cnt]=h[i];
	for (int i=1;i<which;++i) a[++cnt]=h[i];
	for (int i=n;i;--i){
		r[i]=i+1;
		while (r[i]<=n && a[i]>a[r[i]]) r[i]=r[r[i]];
		if (r[i]<=n && a[i]==a[r[i]]) c[i]=c[r[i]]+1,r[i]=r[r[i]];
	}
	for (int i=1;i<=n;++i){
		l[i]=i-1;
		while (l[i]>0 && a[i]>=a[l[i]]) l[i]=l[l[i]];
	}
	for (int i=1;i<=n;++i){
		ans+=(long long)c[i];
		if (a[i]==a[1]) continue;
		if (r[i]==n+1 && l[i]==1) ans++;
		else ans+=2LL;
	}
	printf("%I64d\n",ans);
	return 0;
}


By Charlie Pan

Mar 12,2014

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值