ABC340A～Fの解答[Java]

## はじめに
今回はコンテスト中にEまで、コンテスト後にFを解いたのでそれらを載せようと思います。

なお、僕のライブラリは[提出結果](https://atcoder.jp/contests/abc340/submissions?f.Task=&f.LanguageName=Java&f.Status=AC&f.User=viral)よりご確認下さい。
では、見ていきましょう。

## A - Arithmetic Progression
問題文は[こちら](https://atcoder.jp/contests/abc340/tasks/abc340_a)

$A$が$B$になるまでループを回しながら$D$だけ加算していけば目的の数列を構築できます。
```A.java
final class Main{
	private static final boolean autoFlush = false;
	private static final SimpleScanner sc = new SimpleScanner(System.in);
	private static final SimpleWriter out = new SimpleWriter(System.out,autoFlush);

	public static void main(String[] args){

		//A、B、Dの受け取り
		int A = sc.nextInt();
		int B = sc.nextInt();
		int D = sc.nextInt();

  		//Bになるまでループ
		for(;A!=B;A+=D)
			out.print(A+" ");

   		//最後は空白じゃなくて改行
		out.println(B);

		out.close();
	}
}
```

## B - Append
問題文は[こちら](https://atcoder.jp/contests/abc340/tasks/abc340_b)

動的に要素を追加したいので`ArrayList<Integer>`で処理しました。
```B.java
final class Main{
	private static final boolean autoFlush = false;
	private static final SimpleScanner sc = new SimpleScanner(System.in);
	private static final SimpleWriter out = new SimpleWriter(System.out,autoFlush);

	public static void main(String[] args){

		//Qの受け取り
		int Q = sc.nextInt();
		ArrayList<Integer> A = new ArrayList<>();

  		//問題文通りに処理
		while(Q-->0){
			int t = sc.nextInt();
			if(t==1)
				A.add(sc.nextInt());
			else
				out.println(A.get(A.size()-sc.nextInt()));
		}

		out.close();
	}
}
```

## C - Divide and Divide
問題文は[こちら](https://atcoder.jp/contests/abc340/tasks/abc340_c)

一番大きい値を貪欲に選んでいくことを考えると、値をkey、個数をvalueとした`TreeMap<Long,Long>`で処理できると考え、これで実装しました。
```C.java
final class Main{
	private static final boolean autoFlush = false;
	private static final SimpleScanner sc = new SimpleScanner(System.in);
	private static final SimpleWriter out = new SimpleWriter(System.out,autoFlush);

	public static void main(String[] args){

		//Nの受け取り
		long N = sc.nextLong();

  		//Mapで黒板に書いてある値を管理
		TreeMap<Long,Long> map = new TreeMap<>();
		long ans = 0;
		map.put(N,1L);

  		//操作できなくなるまで回す
		while(map.size()>0){
			Map.Entry<Long,Long> entry = map.pollLastEntry();
			long key = entry.getKey();
			long val = entry.getValue();
   
			if(key>1){ //操作できるなら次の値を書き込む
				ans += key*val;
				map.merge(key/2,val,Long::sum);
				map.merge((key+1)/2,val,Long::sum);
			}
		}

  		//答えの出力
		out.println(ans);

		out.close();
	}
}
```

## D - Super Takahashi Bros.
問題文は[こちら](https://atcoder.jp/contests/abc340/tasks/abc340_d)

ダイクストラ法で解ける見た目なので(単一頂点からの最短経路問題なので)、それで解きました。
```D.java
final class Main{
	private static final boolean autoFlush = false;
	private static final SimpleScanner sc = new SimpleScanner(System.in);
	private static final SimpleWriter out = new SimpleWriter(System.out,autoFlush);

	public static void main(String[] args){

		//Nの受け取り
		int N = sc.nextInt();

  		//隣接行列の構築
		ArrayList<ArrayList<int[]>> list = new ArrayList<>();
		for(int i=0;i<=N;i++)
			list.add(new ArrayList<>());
		for(int i=1;i<N;i++){
			int A = sc.nextInt();
			int B = sc.nextInt();
			int X = sc.nextInt();
			list.get(i).add(new int[]{i+1,A});
			list.get(i).add(new int[]{X,B});
		}

  		//Queueに乗せるようのクラス
		class Node{
			int now;
			long val;
			public Node(int n,long v){
				now = n;
				val = v;
			}
		}

  		//初期値設定
		PriorityQueue<Node> queue = new PriorityQueue<>((a,b)->Long.compare(a.val,b.val));
		queue.add(new Node(1,0));
		long[] cost = new long[N+1];
		Arrays.fill(cost,Long.MAX_VALUE);
		cost[1] = 0;

  		//ダイクストラ
		while(queue.size()>0){
			Node node = queue.poll();
			if(node.val==cost[node.now]){
				for(int[] path:list.get(node.now)){
					if(cost[node.now]+path[1]<cost[path[0]]){
						cost[path[0]] = cost[node.now]+path[1];
						queue.add(new Node(path[0],cost[path[0]]));
					}
				}
			}
		}

  		//答えの出力
		out.println(cost[N]);

		out.close();
	}
}
```

## E - Mancala 2
問題文は[こちら](https://atcoder.jp/contests/abc340/tasks/abc340_e)

区間への加算が必要なので遅延セグメントツリーで処理しました。
```E.java
final class Main{
	private static final boolean autoFlush = false;
	private static final SimpleScanner sc = new SimpleScanner(System.in);
	private static final SimpleWriter out = new SimpleWriter(System.out,autoFlush);

	public static void main(String[] args){

		//N、Mの受け取り
		int N = sc.nextInt();
		int M = sc.nextInt();

  		//セグ木に乗せたかったのでラッパークラスで
		Long[] A = new Long[N];
		for(int i=0;i<N;i++)
			A[i] = sc.nextLong();

   		//Bの受け取り
		int[] B = sc.nextInt(M);

  		//遅延セグ木
		LazySegmentTree<Long,Long> lSegT = new LazySegmentTree<>(A,0L,0L,false){
			public Long mapping(Long a,Long b){
				return Long.sum(a,b);
			}
			public Long composition(Long a,Long b){
				return Long.sum(a,b);
			}
			public Long function(Long a,Long b){
				return Long.sum(a,b);
			}
		};

  		//Bに沿って処理
		for(int num:B){
			long sum = lSegT.get(num);
			lSegT.update(num,0L);
			lSegT.apply(0,N,sum/N);
			sum %= N;
			if(N<sum+num+1)
				lSegT.apply(0,(int)sum+num+1-N,1L);
			if(num<N)
				lSegT.apply(num+1,Math.min(N,num+(int)sum+1),1L);
		}

  		//石の数を求めて配列に
		Long[] ans = new Long[N];
		for(int i=0;i<N;i++)
			ans[i] = lSegT.get(i);
		out.println(ans);

		out.close();
	}
}
```
定数倍が重いのもあってちょっと実行時間がキツめ…。

## F - S = 1
問題文は[こちら](https://atcoder.jp/contests/abc340/tasks/abc340_f)

証明は[公式解説](https://atcoder.jp/contests/abc340/editorial/9250)に任せますが、拡張ユークリッドの互除法を用いて解きました。
```F.java
import java.util.Scanner;
class Main{
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);

  		//X、Yの受け取り
		long X = sc.nextLong();
		long Y = sc.nextLong();

  		//何となく絶対値で拡張ユークリッド
		long[] d = extendedGcd(Math.abs(X),Math.abs(Y));

  		//最大公約数が2より大きいなら無理
		if(d[0]>2){
			System.out.println(-1);
			return;
		}

  		//値調整
		if(d[0]==1){
			d[1] *= 2;
			d[2] *= 2;
		}
		if(Long.signum(X)==Long.signum(Y)){
			d[1] *= -1;
		}

  		//答えの出力
		System.out.println(d[2]+" "+d[1]);
	}

 	//拡張ユークリッドの互除法
  	//aX+bY=gcd(a,b)を満たすとき、new long[]{gcd(a,b), X, Y}が返ってくる
	private static long[] extendedGcd(long a,long b){
		if(b==0){
			return new long[]{a,1,0};
		}
		long[] d = extendedGcd(b,a%b);
		d[1] -= a/b*d[2];
		return new long[]{d[0],d[2],d[1]};
	}
}
```
符号こねくり回してしまって本番中解けなかった…。

## 感想
A,B,C,D:易しい
E:遅延セグ木はFなイメージが少しあったけど、まぁ別解もあるからEが妥当なのかな
F:うぉぉぉぉぉぉぉぉぉん😭😭😭😭😭😭😭😭😭😭
って感じでした。

ギリギリ青に留まれましたが、次回が…怖い…。