比赛地址:http://acm.hust.edu.cn:8080/judge/contest/view.action?cid=17732#overview
第一题:给你一个数,看能不能分割成两个偶数
分析:水到不贴代码了。。。
第二题:给你一个数,能不能分割成n份,每份有上下限
分析:直接贪心搞定。。。
第三题:要求写一个注册系统,如果一个名字没出现过,就返回OK,如果出现过,就自动在末尾加数字,从1开始,直到这个新名字没出现过,并返回给用户,同时保存在数据库里。。。
分析:按这个题面描述,它是一道难题,不过由于题目是错的,所以只需要判断一个名字出现几次,在后面多输出那个次数就行。。。
为什么说题目错了呢?下面这组数据告诉你:
3
t1
t
t
这样,估计你们的程序都会输出
OK
OK
t1
呵呵,不解释了,反正因此我把他当难题,然后被虐成渣了
代码:
#include<cstdio> #include<iostream> #include<cstring> using namespace std; const int mm=1000007; struct hashtable { int h[mm],p[mm],size; int d[111111]; char s[111111][44]; int hash(char *a) { int id=0; while(*a)id=id*131+(*a++); return (id&0x7FFFFFFF)%mm; } int insert(char *a) { int i,id=hash(a); for(i=h[id];i>=0;i=p[i]) if(!strcmp(a,s[i]))return i; d[size]=1; strcpy(s[size],a); p[size]=h[id],h[id]=size++; return -1; } void clear() { size=0; memset(h,-1,sizeof(h)); } }g; char str[44]; int i,n; int main() { while(~scanf("%d",&n)) { g.clear(); while(n--) { scanf("%s",str); i=g.insert(str); if(i<0)puts("OK"); else { printf("%s%d\n",str,g.d[i]); ++g.d[i]; } } } return 0; }
分析:我们按每个信封的宽排序,如果宽相同,再按长排序,然后,你应该会发现,这个跟最长地增字序列很像,为什么说是很像,而不是一样呢,因为对于宽相同的是不能放在一起的。。。我之前忽略这个问题,加了二分优化,反而挂了= =
代码:
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int mm=111111; struct data { int w,h,id; }g[mm]; int f[mm],p[mm]; int i,j,k,ans,n,w,h; bool cmp(data a,data b) { return a.w<b.w||(a.w==b.w&&a.h<b.h)||(a.w==b.w&&a.h==b.h&&a.id>b.id); } void out(int j) { if(j<0)return; out(p[j]); printf("%d%c",g[j].id,--ans?' ':'\n'); } int main() { while(~scanf("%d%d%d",&n,&w,&h)) { for(i=0;i<n;++i) scanf("%d%d",&g[i].w,&g[i].h),g[i].id=i+1; sort(g,g+n,cmp); for(i=0;i<n;++i) if(g[i].w>w&&g[i].h>h)f[i]=1; else f[i]=-1e7; for(i=0;i<n;++i) for(p[i]=-1,j=0;j<i;++j) if(g[j].w<g[i].w&&g[j].h<g[i].h&&f[j]+1>f[i]) { f[i]=f[j]+1; p[i]=j; } for(i=j=0;i<n;++i) if(f[i]>f[j])j=i; ans=f[j]; if(ans>0) { printf("%d\n",ans); out(j); } else puts("0"); } return 0; }