ABC278A～Eの解答[Java]

## はじめに
今回はEまでコンテスト中に書いた物を載せようと思います。

では、見ていきましょう。

## A - Shift
問題文は[こちら](https://atcoder.jp/contests/abc278/tasks/abc278_a)

$N \gt K$の時は$K+1$番目から$N$番目までの要素を出力後、$K$個$0$を出力しました。
$N \le K$の時は$N$個$0$を出力しました。
```A.java
class Main{
 
	static final boolean autoFlush = false;
	static final Library System = new Library(java.lang.System.in,java.lang.System.out,java.lang.System.err,autoFlush);
 
	public static void main(String[] args){
 
		//N、K、Aの受け取り
		int N = System.in.nextInt();
		int K = System.in.nextInt();
		int[] A = System.in.nextInt(N);

		//場合分けして出力
		if(N>K){
			System.out.print(A[K]);
			for(int i=K+1;i<N;i++)
				System.out.print(" "+A[i]);
			for(int i=0;i<K;i++)
				System.out.print(" 0");
			System.out.println();
		}else{
			for(int i=0;i<N;i++)
				System.out.print(0+" ");
			System.out.println();
		}
 
		System.out.close();
	}
}
```
Twitterで見かけましたが、ArrayDequeでやった方が簡潔に書けましたね。

## B - Misjudge the Time
問題文は[こちら](https://atcoder.jp/contests/abc278/tasks/abc278_b)

ちょっとごちゃごちゃやってしまいましたが、
$A=H/10$、$B=H$%$10$、$C=W/10$、$D=W$%$10$
として、$10A+C<24$と$B\lt6$を満たすまで時間を進めていきました。
``` B.java
class Main{
 
	static final boolean autoFlush = false;
	static final Library System = new Library(java.lang.System.in,java.lang.System.out,java.lang.System.err,autoFlush);
 
	public static void main(String[] args){
 
		//H、Wを受け取って整形
		int H = System.in.nextInt();
		int A = H/10;
		int B = H%10;
		int W = System.in.nextInt();
		int C = W/10;
		int D = W%10;

		//条件を満たすまで時間を進めていく
		while(!(A*10+C<24&&B<6)){
			D++;
			if(D==10){
				C++;
				D = 0;
			}
			if(C==6){
				B++;
				C = 0;
			}
			if(B==10){
				A++;
				B = 0;
			}
			if(A==2&&B==4){
				A = 0;
				B = 0;
			}
		}

		//答えの出力
		System.out.println(A+""+B+" "+C+""+D);
 
		System.out.close();
	}
}
```
LocalTimeってのを使えばもっと楽だったっぽいです(Twitterで見かけた)。

## C - FF
問題文は[こちら](https://atcoder.jp/contests/abc278/tasks/abc278_c)

TreeMapに$i$番目の人が誰をフォローしているかを記録するHashSetを記録することで情報を保持して解きました。
```C.java
class Main{
 
	static final boolean autoFlush = false;
	static final Library System = new Library(java.lang.System.in,java.lang.System.out,java.lang.System.err,autoFlush);
 
	public static void main(String[] args){
 
		//N、Qの受け取り
		int N = System.in.nextInt();
		int Q = System.in.nextInt();

		//フォローしている人を記録するmap
		TreeMap<Integer,HashSet<Integer>> list = new TreeMap<>();

		//getOrDefault用の空っぽのset
		HashSet<Integer> empty = new HashSet<>();
		while(Q-->0){

			//T、A、Bの受け取り
			int T = System.in.nextInt();
			int A = System.in.nextInt();
			int B = System.in.nextInt();

			//1ならAにBを追加
			if(T==1){
				HashSet<Integer> temp = list.remove(A);
				if(temp==null)
					temp = new HashSet<Integer>();
				temp.add(B);
				list.put(A,temp);

			//2ならAからBを消す
			}else if(T==2){
				HashSet<Integer> temp = list.remove(A);
				if(temp==null)
					temp = new HashSet<Integer>();
				temp.remove(B);
				list.put(A,temp);

			//3なら互いにフォローしてるか返す
			}else{
				boolean flag = list.getOrDefault(A,empty).contains(B);
				flag &= list.getOrDefault(B,empty).contains(A);
				System.out.println(flag?"Yes":"No");
			}
		}
 
		System.out.close();
	}
}
```
まぁ特に問題はなさそうですね。

## D - All Assign Point Add
問題文は[こちら](https://atcoder.jp/contests/abc278/tasks/abc278_d)

クエリが$2$、$3$の時は特に問題無いんですが$1$のクエリがいっぱい出てきてそのたびに配列を全部書き換えていては到底間に合わなそうと思ったので、基準からいくつ加算されているかをTreeMapで保持する形で処理しました。
```D.java
class Main{
 
	static final boolean autoFlush = false;
	static final Library System = new Library(java.lang.System.in,java.lang.System.out,java.lang.System.err,autoFlush);
 
	public static void main(String[] args){
 
		//N、Aの受け取り
		int N = System.in.nextInt();
		TreeMap<Integer,Long> A = new TreeMap<>();
		for(int i=1;i<=N;i++)
			A.put(i,System.in.nextLong());

		//全体の数値
		long now = 0;

		//Qの受け取り
		int Q = System.in.nextInt();
		while(Q-->0){

			//クエリの受け取り
			int q = System.in.nextInt();

			//1ならTreeMapを空っぽにしてnowを更新
			if(q==1){
				int x = System.in.nextInt();
				now = x;
				A.clear();

			//2ならmapに記録
			}else if(q==2){
				int i = System.in.nextInt();
				int x = System.in.nextInt();
				Long temp = A.remove(i);
				if(temp==null)
					temp = 0L;
				A.put(i,temp+x);

			//3ならmapの値とnowを足して出力
			}else{
				int i = System.in.nextInt();
				long ans = A.getOrDefault(i,0L);
				System.out.println(now+ans);
			}
		}
 
		System.out.close();
	}
}
```
これもそこまで難しくは感じませんでした。

## E - Grid Filling
問題文は[こちら](https://atcoder.jp/contests/abc278/tasks/abc278_e)

累積和で解きました。三次元配列で
$sum[i][j][k]:$左上と$i$行$j$列目を対角とする長方形内に存在する$k$の個数
として処理しました。
```E.java
class Main{
 
	static final boolean autoFlush = false;
	static final Library System = new Library(java.lang.System.in,java.lang.System.out,java.lang.System.err,autoFlush);
 
	public static void main(String[] args){

		//各値の受け取り
		int H = System.in.nextInt();
		int W = System.in.nextInt();
		int N = System.in.nextInt();
		int h = System.in.nextInt();
		int w = System.in.nextInt();
		int[][] A = System.in.nextInt(H,W);

		//累積和用3次元配列
		int[][][] sum = new int[H+1][W+1][N+1];

		//和をとる
		for(int i=1;i<=H;i++){
			for(int j=1;j<=W;j++){
				sum[i][j][A[i-1][j-1]]++;
				for(int k=1;k<=N;k++)
					sum[i][j][k] += sum[i-1][j][k]+sum[i][j-1][k]-sum[i-1][j-1][k];
			}
		}

		//h*wの右下を決めて数え上げ
		for(int i=h;i<=H;i++){
			for(int j=w;j<=W;j++){
				int count = 0;
				for(int k=1;k<=N;k++)
					if(sum[H][W][k]>sum[i][j][k]-sum[i-h][j][k]-sum[i][j-w][k]+sum[i-h][j-w][k])
						count++;
				System.out.print(count);
				System.out.print(' ');
			}
			System.out.println();
		}
 
		System.out.close();
	}
}
```
最初ArrayList\<ArrayList\<HashMap\<Integer,Integer>>>とかで保持してTLEしまくりました。

## 感想
A、B:ちょっとめんどくさかった
C、D:そんなに難しくない･･･？
E:配列で処理する、という発想になるまでにとんでもない時間がかかってしまった･･･
って感じでした。

Eまで解いたのにレートが下がる回でした･･･悲しい･･･。