はじめに
解答は提出そのままではなく書き直せる部分を書き直したものです。
それでは、見ていきましょう。
A - Move Right
問題文はこちら
問題文は「先頭三文字の先頭に0を付けて出力せよ」と同義なのでまんま実装してやりましょう。
import java.util.*;
class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
//文字の受け取り
String str = sc.nextLine();
//文字を切り出して出力
System.out.println("0"+str.substring(0,3));
}
}
特に説明はいらないですかね。ちなみにこのコードで135msです。多分BufferedReaderクラスとか有志のFastScannerクラスを使えば60~80msくらい出せるんじゃないですかね。
B - Unique Nicknames
問題文はこちら
なぜか先頭から見ていったときに重複を省いたコードを書いたらWA出たんですよね。ってことで重複を含めた全探索をして確固たる解答を出してやりましょう。
import java.io.*;
class Main{
public static void main(String[] args)throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//Nと名前の受け取り
int N = Integer.parseInt(br.readLine());
String[][] str = new String[N][2];
for(int i=0;i<N;i++){
str[i] = br.readLine().split(" ");
}
//全探索
for(int i=0;i<N;i++){
//名字と名前が被ってないか管理するboolean型変数
boolean first = false;
boolean family = false;
//先頭から被りがないか見ていく
for(int j=0;j<N;j++){
if(i==j)
continue; //同一人物は探索から省く
//名字被ってる?
if(str[i][0].equals(str[j][0])||str[i][0].equals(str[j][1]))
family = true;
//名前被ってる?
if(str[i][1].equals(str[j][0])||str[i][1].equals(str[j][1]))
first = true;
}
//名字も名前も被った?
if(first&&family){
System.out.println("No");
System.exit(0);
}
}
//全部被ってなければ出力
System.out.println("Yes");
}
}
実は未だにWAの理由がいまいちわかってないんですよね。あとでいろいろ試してみます。
C - 1 2 1 3 1 2 1
問題文はこちら
入茶記事でも書いた問題ですね。もはや説明をここに書く必要も無い気がしますが、入茶記事を見ていない人のためにも再度書きます。
import java.util.*;
import java.io.*;
class Main{
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static PrintWriter pw = new PrintWriter(System.out);
public static void main(String[] args)throws IOException{
//Nの受け取り
int N = Integer.parseInt(br.readLine());
//初期解"1"を先行出力
pw.print(1);
//N>1の時の処理
for(int i=2;i<(1<<N);i++){
int temp = i;
//文字間のスペース
pw.print(" ");
//i番目の数字はiを素因数分解したときの2の指数+1
for(int j=1;;j++){
//2で割れなくなったら終わり
if((temp%2)==1){
pw.print(j);
break;
}
//2で割る(右シフト)
temp>>=1;
}
}
//改行してflush
pw.println();
pw.close();
}
}
133ms出せてるんで十分じゃないでしょうか。多分。
D - Cylinder
問題文はこちら
最初はArrayListでやってやろうとしましたがArrayListのgetは配列に比べてかなり遅いのでTLEになってしまうのではないかと思って配列で無理矢理実装しました。多分ArrayListでもいけたんじゃないですかね(どうせ先頭と後ろしか見ないからDequeでもいいのかな?)。
import java.util.*;
class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
//クエリの個数の受け取り
int Q = sc.nextInt();
//どうせ200000以上いれることはないので200000要素確保
int[][] Cylinder = new int[200000][2];
//今残量が残っている中で先頭のindex、一番後ろのindexを管理する変数
int pick1 = 0;
int pick2 = 0;
//一個ずつ読み込み
for(int i=0;i<Q;i++){
int temp = sc.nextInt();
//入れるとき?
if(temp==1){
int x = sc.nextInt();
int c = sc.nextInt();
//0番目に数字を、1番目に個数を記録
Cylinder[pick1][0] = x;
Cylinder[pick1][1] = c;
//indexを調整
pick1++;
}
//取り出すとき?
else if(temp==2){
int c = sc.nextInt();
//合計を記録しておく変数
long ans = 0;
//残量に合った処理をする
for(int j=0;j<c;){ //cは取り出す数、jは取り出した数
//残量の方が多い?
if(Cylinder[pick2][1]>=c-j){
Cylinder[pick2][1] -= (c-j);
ans += (long)Cylinder[pick2][0]*(c-j);
j = c; //breakでも良い
}
//取り出す量の方が多い?(indexの更新が必要か?)
else{
ans += (long)Cylinder[pick2][0]*Cylinder[pick2][1];
j += Cylinder[pick2][1];
Cylinder[pick2][1] = 0; //残量ゼロ(やらなくても良い)
//index調整
pick2++;
}
}
System.out.println(ans);
}
//別にいらないけどもし入力ミスが有れば終わり
else{
System.exit(1);
}
}
}
}
当時は念のため…ってのでいろいろ余計な実装もしてましたが、省いても200msくらいしか変わらず、結局1000msかかっちゃうんですよね。しょうがないのかな…。
って思ってたんですが、提出一覧見てると176msの人がいますね…。すげぇや…。後で機会があれば書き直してみます。
総評
A:まぁ、いわゆるやるだけ。
B:ちょっと気を抜くとWA。慎重に。
C:楽しかった!こんな問題を解きたい。
D:うーん…。改善すべきコードで終わってしまった…。
って感じでした。
いろいろ考えられそうな問題ばかりで非常に面白いコンテストでしたね。