読者です 読者をやめる 読者になる 読者になる

Intel Code Challenge Elimination Round (Div.1 + Div.2, combined)

これはどうするべきだったのだろうか......

A B C D E F Place
00:03 00:07 00:18 00:31 -5 - 154th

順位が低いのは、本番がHackゲーだったからなので仕方がないが、仮にHackできる環境だったとしても50位くらいだと思う。Eが解けてないのが大問題。

A:
空気。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;

int main(){
	int a;scanf("%d",&a);
	int H,M;
	scanf("%d:%d",&H,&M);
	if(a==24){
		if(H>23){
			H%=10;
		}
	}else{
		if(H==0){
			H=1;
		}else if(H>12){
			if(H%10)H%=10;
			else H=10;
		}
	}
	if(M>=60){
		M%=10;
	}
	printf("%02d:%02d\n",H,M);
}

B:
未だに1行読むのが苦手。入力にスペースを含まないでほしい。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
int p[110];
char in[210];
int main(){
	int a;scanf("%d",&a);
	for(int i=0;i<a;i++)scanf("%d",p+i);
	gets(in);
	for(int i=0;i<a;i++){
		gets(in);
		int cnt=0;
		for(int j=0;in[j];j++){
			if(in[j]=='a'||in[j]=='i'||in[j]=='u'||in[j]=='e'||in[j]=='o'||in[j]=='y'){
				cnt++;
			}
		}
		if(cnt!=p[i]){
			printf("NO\n");return 0;
		}
	}
	printf("YES\n");
}

C:
やるだけ。冗長すぎ。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
long long sum[110000];
int p[110000];
int L[110000];
int R[110000];
int q[110000];
long long ans[110000];
int v[110000];
int UF[110000];
vector<int> ct[110000];
long long tot[110000];
int FIND(int a){
	if(UF[a]<0)return a;
	return UF[a]=FIND(UF[a]);
}
long long cur=0;
void UNION(int a,int b){
	a=FIND(a);b=FIND(b);if(a==b)return;
	if(UF[a]>UF[b])swap(a,b);
	for(int i=0;i<ct[b].size();i++)ct[a].push_back(ct[b][i]);
	tot[a]+=tot[b];
	cur=max(cur,tot[a]);
	ct[b].clear();
	UF[a]+=UF[b];UF[b]=a;
}
int main(){
	int a;scanf("%d",&a);
	for(int i=0;i<a;i++)scanf("%d",p+i);
	for(int i=0;i<a;i++){
		sum[i+1]=sum[i]+p[i];
	}
	for(int i=0;i<a;i++){
		scanf("%d",q+i);q[i]--;
	}
	for(int i=0;i<a;i++){
		UF[i]=-1;
		ct[i].push_back(p[i]);
		tot[i]=p[i];
	}
	for(int i=a-1;i>=0;i--){
		ans[i]=cur;
		v[q[i]]=1;
		cur=max(cur,tot[FIND(q[i])]);
		if(q[i]&&v[q[i]-1]){
			UNION(q[i],q[i]-1);
		}
		if(q[i]<a-1&&v[q[i]+1]){
			UNION(q[i],q[i]+1);
		}
	}
	for(int i=0;i<a;i++)printf("%I64d\n",ans[i]);
}

D:
Greedyにつめていく。上位勢速すぎだった。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
int b[60000];
int ans[60000];
int n;
bool chk(int a){
	set<int>S;
	for(int i=0;i<n;i++){
		int c=b[i];
		bool ok=false;
		while(c){
			if(c<=a&&!S.count(c)){
				ok=true;break;
			}
			c/=2;
		}
		if(!ok)return false;
		S.insert(c);
		ans[i]=c;
	}
	return true;
}
int main(){
	int a;scanf("%d",&a);
	n=a;
	for(int i=0;i<a;i++)scanf("%d",b+i);
	int left=0;
	int right=mod;
	while(left+1<right){
		int M=(left+right)/2;
		if(chk(M)){
			right=M;
		}else left=M;
	}
	chk(right);
	for(int i=0;i<a;i++){
		if(i)printf(" ");printf("%d",ans[i]);
	}
	printf("\n");
}

E:
20回以上変なマスを踏むケースは踏む回数の偶奇で符号を変えて足してまとめてしまえばいいと思うんだけど、うまくいかない。嘘なのだろうか?

F:
こっちをやったほうがよかった説

総評として、こういうセットでやるだけしかできないとやるだけパートが瞬殺すぎるのも相まって本当につまらない