[JAVA] ABC --125- A & B & C & D

AtCoder ABC 125 A&B&C&D AtCoder - 125

Explanation Broadcast

2019/05/22 Add the problem name

2019/06/27 Added seg tree solution for C problem

A - Biscuit Generator

--T + 0.5 hours can be added for biscuits

	private void solveA() {
		int a = nextInt();
		int b = nextInt();
		int t = nextInt();

		int res = 0;

		//		double time = 0;
		//		while ((time += a) <= (t + 0.5)) {
		//			res += b;
		//		}

		res = t / a * b;

		out.println(res);
	}

B - Resale

--X is $ \ sum_ {i = 1} ^ {n} V_i $ --Y is $ \ sum_ {i = 1} ^ {n} C_i $ -Because it is the maximum value of $ X-Y $ --X should be larger -Do not count pairs with $ V_i <C_i $

	private void solveB() {
		int numN = nextInt();
		int[] v = IntStream.range(0, numN).map(i -> nextInt()).toArray();
		int[] c = IntStream.range(0, numN).map(i -> nextInt()).toArray();

		long res = 0;
		for (int i = 0; i < numN; i++) {
			if (v[i] > c[i]) {
				res += (v[i] - c[i]);
			}
		}

		out.println(res);
	}

C - GCD on Blackboard

Cumulative sum

--Take the cumulative sum of GCD from the left and right and exclude unnecessary parts

position GCD
1 2 3 4 5 1-5 GCD
i=1 2 3 4 5 2-5 GCD
i=2 1 3 4 5 1 and 3-5 GCD
i=3 1 2 4 5 1-2 and 4-5 GCD
i=4 1 2 3 5 1-3 and 5 GCD
i=5 1 2 3 4 1-4 GCD

-When $ i = 3 $, if you take GCD with GCD $ of $ 1-2 and GCD $ of $ 4-5, it will be the total GCD. - gcd(1-2,4-5) --To achieve the above, create and merge 1-5 GCD and 5-1 GCD.

/*
	 *Audio description broadcast
	 * https://www.youtube.com/watch?v=8lm8o8L9Bmw
	 */
	private void solveC() {
		int numN = nextInt();
		int[] wk = IntStream.range(0, numN).map(i -> nextInt()).toArray();

		long[] forward = new long[numN];
		long[] backward = new long[numN];

		long forGcd = 0;
		long backGcd = 0;
		for (int i = 0; i < numN; i++) {
			forGcd = forward[i] = getGcd(forGcd, wk[i]);
			backGcd = backward[numN - 1 - i] = getGcd(backGcd, wk[numN - 1 - i]);
		}
		long max = 1;

		for (int i = 0; i < numN; i++) {
			if (i == 0) {
				max = Long.max(max, backward[i + 1]);
			} else if (i == numN - 1) {
				max = Long.max(max, forward[i - 1]);
			} else {
				max = Long.max(max, getGcd(forward[i - 1], backward[i + 1]));
			}
		}
		out.println(max);
	}

	private long getGcd(long num1, long num2) {
		long max = Long.max(num1, num2);
		long min = Long.min(num1, num2);
		if (min == 0) {
			return max;
		}
		long amari = max % min;

		while (amari != 0) {
			max = min;
			min = amari;
			amari = max % min;
		}
		return min;

	}

TLE

――Well, because it's a reminder, this is also ...

	private void solveC2() {
		int numN = nextInt();
		int[] wk = IntStream.range(0, numN).map(i -> nextInt()).toArray();

		long maxGcd = 0;

		for (int i = 0; i < numN; i++) {
			long max = 0;
			for (int j = 0; j < numN; j++) {
				if (i == j) {
					continue;
				}
				max = getGcd(max, wk[j]);
			}
			maxGcd = Long.max(maxGcd, max);
		}
		out.println(maxGcd);
	}

Solved with seg tree

reference: Kenchon's competition professional devotion record For you who want to write a segment tree in Sora Complete domination / query processing technique on the tree Data structure in programming contest Programming Contest Challenge Book P.153 ~


	/**
	 * segment tree version
	 *
	 *Input value sample
	 * [P-1]
	 * 3
	 * 7 6 8
	 *
	 * [P-2]
	 * 6
	 * 12 3 6 9 15 11
	 *
	 */
	private void solveC3() {
		int numN = nextInt();
		int[] wk = IntStream.range(0, numN).map(i -> nextInt()).toArray();

		SegTree tree = new SegTree(numN);

		/*
		 *Before set
		 * [P-1]
		 * [2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647]
		 *
		 * [P-2]
		 * [2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647]
		 */
		for (int i = 0; i < wk.length; i++) {
			tree.set(i, wk[i]);
		}
		/*
		 *Immediately after the set is finished
		 * [P-1]
		 * [2147483647, 2147483647, 2147483647, 2147483647, 7, 6, 8, 2147483647]
		 *
		 * [P-2]
		 * [2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 12, 3, 6, 9, 15, 11, 2147483647, 2147483647]
		 *
		 */
		tree.update();
		/*
		 *Immediately after the update is finished
		 * [P-1]
		 * [2147483647, 1, 1, 1, 7, 6, 8, 2147483647]
		 *
		 *leaf is a value and node is a common divisor
		 *  1( k 1)
		 *     |----------------------|
		 *     |                      |
		 *  1(2k 2)               1(2k+1 3)
		 *     |--------|             |----------|
		 *     |        |             |          |
		 *  7(2k 4) 6(2k+1 5)     8(2k 6)   2147483647(2k+1 7)
		 *
		 *
		 *  [P-2]
		 *  [2147483647, 1, 3, 1, 3, 3, 1, 2147483647, 12, 3, 6, 9, 15, 11, 2147483647, 2147483647]
		 *
		 *  1( k 1)
		 *     |----------------------------------------|
		 *     |                                        |
		 *  3(2k 2)                                  1(2k+1 3)
		 *     |-----------------|                      |------------------------|
		 *     |                 |                      |                        |
		 *  3(2k 4)            3(2k+1 5)             3(2k 6)                  2147483647(2k+1 7)
		 *     |-------|         |------------|         |----------|             |--------------------|
		 *     |       |         |            |         |          |             |                    |
		 * 12(2k 8)  3(2K+1 9)  6(2k 10)  9(2K+1 11) 15(2k 12)  11(2K+1 13)   2147483647(2k 14)    2147483647(2k+1 15)
		 */

		long res = 0;

		for (int i = 0; i < numN; i++) {
			/*
			 *Half-open section[)
			 * 0 - i
			 *GCD(i not included)
			 */
			long left = tree.get(0, i);
			/*
			 *Half-open section[)
			 * i+1 - numN(numN not included)
			 *GCD
			 */
			long right = tree.get(i + 1, numN);
			res = Long.max(res, getGcd(left, right));

		}

		out.println(res);
	}

	/**
	 * segment tree
	 *Complete binary tree
	 * @author pc9801bx2
	 *
	 */
	private static class SegTree {

		private long[] dat;
		private int numOfElmSize;
		private int numOfElm;

		private SegTree(int numOfElm) {
			this.numOfElm = numOfElm;
			numOfElmSize = 1;
			/*
			 *Size adjustment
			 *Determining the number of required elements
			 *Example: numOfElm==If 3 is numOfElmSize==4
			 */
			while (numOfElmSize < numOfElm) {
				numOfElmSize *= 2;
			}

			/*
			 *Creating an array
			 * numOfElm==If 3 is size==8
			 */
			dat = new long[numOfElmSize * 2];
			Arrays.fill(dat, Integer.MAX_VALUE);
		}

		/**
		 *Create a parent node
		 */
		private void update() {
			/*
			 * segment tree
			 *Since the leaf arrangement is packed from the back, search from the back
			 * dat[numOfElmSize]← Leftmost leaf
			 * dat[numOfElmSize + n]← Rightmost leaf
			 */
			int k = numOfElmSize - 1;
			/*
			 *At this point there is only data on the leaves
			 *Make sequentially from the rightmost end of the array
			 */
			while (k > 0) {
				/*
				 *k parent
				 * K*2 left side
				 * k*2+1 right side
				 *Create from the parent of the leftmost leaf
				 */
				dat[k] = getInnerGcd(dat[k * 2], dat[k * 2 + 1]);
				k--;
			}

		}

		/**
		 *Set of values
		 *
		 * @param a
		 * @param val
		 */
		private void set(int a, int val) {
			/*
			 *The one that corresponds to the first leaf
			 *Set in the second half of the array
			 *Put it in a place larger than numOfElmSize
			 */
			dat[a + numOfElmSize] = val;
		}

		/**
		 *
		6
		12 3 6 9 15 11
		 [2147483647, 1, 3, 1, 3, 3, 1, 2147483647, 12, 3, 6, 9, 15, 11, 2147483647, 2147483647]

		 1( k 1)
		    |----------------------------------------|
		    |                                        |
		 3(2k 2)                                  1(2k+1 3)
		    |-----------------|                      |------------------------|
		    |                 |                      |                        |
		 3(2k 4)            3(2k+1 5)             3(2k 6)                  2147483647(2k+1 7)
		    |-------|         |------------|         |----------|             |--------------------|
		    |       |         |            |         |          |             |                    |
		 12(2k 8)  3(2K+1 9)  6(2k 10)  9(2K+1 11) 15(2k 12)  11(2K+1 13)   2147483647(2k 14)    2147483647(2k+1 15)


The transition when moving i one by one to the right is described below.
		-------------------
		 [0:0):GCD=0
		 left 8
		 right 8

		 [1:6):GCD=1
		 left 9 -> 5 -> 3
		 right 14 -> 7 -> 3
		-------------------
		 [2:6):GCD=1
		 left 10 -> 5 -> 3
		 right 14 -> 7 -> 3
		-------------------
		 [0:2):GCD=3
		 left 8 -> 4 -> 2
		 right 10 -> 5 -> 2

		 [3:6):GCD=1
		 left 11 -> 6 -> 3
		 right 14 -> 7 -> 3
		-------------------
		 [0:3):GCD=3
		 left 8 -> 4 -> 2
		 right 11 -> 5 -> 2

		 [4:6):GCD=1
		 left 12 -> 6 -> 3
		 right 14 -> 7 -> 3
		-------------------
		 [0:4):GCD=3
		 left 8 -> 4 -> 2 -> 1
		 right 12 -> 6 -> 3 -> 1

		 [5:6):GCD=11
		 left 13 -> 7
		 right 14 -> 7
		-------------------
		 [0:5):GCD=3
		 left 8 -> 4 -> 2 -> 1
		 right 13 -> 6 -> 3 -> 1

		 [6:6):GCD=0
		 left 14
		 right 14
		 */
		private long get(int a, int b) {
			long leftGcd = 0;
			long rightGcd = 0;
			int left = a + numOfElmSize;
			int right = b + numOfElmSize;
			//			System.out.println("a:b / " + a + " : " + b + " -- left : right / " + left + " : " + right);
			/*
			 *Loop while parents are different
			 *Follow to the top parent to find the greatest common divisor
			 *If you specify the same leaf position, it will not enter the loop,
			 *that is(0,0)(n,n)Therefore, it is not eligible for acquisition in the first place.-> [:)
			 *So, rather, I want 0 to be returned.
			 */
			while (left < right) {
				/*
				 *When the left is an even node, I want the whole range.
				 *So I want to get the parent instead of getting it here.
				 *For even nodes
				 *myself->My parents->Even-numbered nodes on the right that are not paired->Transition with the parent on the right
				 ** If all are even, and if it becomes odd in the middle, move to the transition of odd nodes.
				 *
				 *However, in the case of odd nodes (the leaves may be even but the nodes may be odd),
				 *I have to take only the child and move to the right without taking the parent, so
				 *Get individual values (leftGcd==0 In other words, in the case of leaves, take the value of leaves)
				 *By the way, leftGcd==If 0, dat[i]Is returned.
				 *For odd nodes,
				 *myself->Even-numbered nodes on the right that are not paired->Transition with the parent on the right
				 */
				if ((left & 1) == 1) {
					leftGcd = getInnerGcd(leftGcd, dat[left]);
					left++;
				}
				/*
				 *When the right is an odd node, I want the whole range. .. But,
				 *Since it is a half-open section, you do not need to leave it on the right.
				 ** I don't take the numN part, but is there any problem? about,
				 *As a matter of fact wk[numN]Since Inf is included in the value of, you can ignore it.
				 *
				 *I want the node to go to the parent as it is(I want the value stored in the parent)So transition to even nodes
				 *Now you can go to your parents the next time you come.
				 * rightGcd==If 0, dat[i]Is returned.
				 *For odd nodes,
				 *myself->Paired left even nodes->Parents and transitions common to you and the left node
				 *
				 *When the right is an even node,
				 *myself->Transition with parent
				 */
				if ((right & 1) == 1) {
					--right;
					rightGcd = getInnerGcd(rightGcd, dat[right]);
				}
				//Select parent node
				left = left / 2;
				right = right / 2;
				//				System.out.println("left : right / " + left + " : " + right);
			}
			long res = getInnerGcd(leftGcd, rightGcd);
			//			System.out.println("res : " + res);
			return res;
		}

		/**
		 *GCD for SegTree
		 * @param num1
		 * @param num2
		 * @return
		 */
		private long getInnerGcd(long num1, long num2) {
			long max = Long.max(num1, num2);
			long min = Long.min(num1, num2);
			if (min == 0) {
				return max;
			}
			long amari = max % min;

			while (amari != 0) {
				max = min;
				min = amari;
				amari = max % min;
			}
			return min;

		}
	}

D --Flipping Signs: Clear copy

――This is easier than C. .. .. I should have done D without going to C. .. ..

--Invert plus and minus two at a time ――If the minus is an even number, you can make a pair and make it a plus. --If the minus is odd, you can't make a pair --In the case of odd numbers, the total can be maximized by making the smallest absolute value negative.

- is even

It is possible to eliminate - from the condition that $ A_i and A_ {i + 1} $ are selected and inverted.

1 2 3 4 total
-1 -2 -3 -4 -10
1,Invert 2 1 2 -3 -4 -4
3,Invert 4 1 2 3 4 10

--Pattern 2 (Even if - is separated, you can move- to make it disappear)

1 2 3 4 total
-1 2 3 -4 0
1,Invert 2 1 -2 3 -4 -2
2,Invert 3 1 2 -3 -4 -4
3,Invert 4 1 2 3 4 10

- is odd

It is impossible to eliminate - due to the condition that $ A_i and A_ {i + 1} $ are selected and inverted.

1 2 3 4 total
1 -2 -3 -4 -8
1,Invert 2 -1 2 -3 -4 -6
3,Invert 4 -1 2 3 4 8

--Pattern 2 (written in a detour on purpose) --Move - to maximize the total -When it is an even number,-can be eliminated, but when it is an odd number, it cannot be eliminated. -instead of,-Can be moved to the minimum value in absolute value (in the figure)|1|To-Is moving) --You can select the target to add - --As a result, it can be the same value as pattern 1.

1 2 3 4 total
-1 -2 -3 4 -8
1,Invert 2 1 2 -3 4 4
3,Invert 4 1 2 3 -4 2
3,Invert 4 1 2 -3 4 4
2,Invert 3 1 -2 3 4 6
1,Invert 2 -1 2 3 4 8

--Another solution is out of understanding

	/*
	 *Merge processes
	 */
	private void solveD() {
		int numN = nextInt();
		int[] wk = new int[numN];

		int mCnt = 0;
		long res = 0;
		int zeroCnt = 0;
		for (int i = 0; i < numN; i++) {
			int val = nextInt();
			if (val < 0) {
				mCnt++;
			}
			if (val == 0) {
				zeroCnt++;
			}
			wk[i] = Math.abs(val);
			res += wk[i];
		}
		Arrays.sort(wk);
		if (mCnt % 2 == 0 || zeroCnt > 0) {
			out.println(res);
		} else {
			out.println(res - Math.abs(wk[0]) * 2);
		}

	}

D --Flipping Signs: A reminder of the thinking process

――I rewrote it because there is a lot of extra processing, but maybe the flow is easier to understand than the clear copy version above?


	/*
	 *For to get or count values can be merged
	 */
	private void solveD2() {
		int numN = nextInt();
		int[] wk = IntStream.range(0, numN).map(i -> nextInt()).toArray();

		int mCnt = 0;
		long res = 0;
		int zeroCnt = 0;
		for (int i = 0; i < numN; i++) {
			/*
			 *Count things less than 0
			 */
			if (wk[i] < 0) {
				mCnt++;
			}
			/*
			 *Get the grand total (abs)
			 */
			res += Math.abs(wk[i]);
			/*
			 *Count 0
			 */
			if (wk[i] == 0) {
				zeroCnt++;
			}
		}
		/*
		 * -If is even or at least one 0
		 *All values+Can be converted to
		 *In that case, simply add up
		 */
		if (mCnt % 2 == 0 || zeroCnt > 0) {
			out.println(res);
			return;
		} else {
			/*
			 * -Is an odd number and there is no 0
			 *In that case,|wk[i]|The smallest value in-Can be maximized by
			 *Rewrite everything with abs once
			 */
			for (int i = 0; i < wk.length; i++) {
				wk[i] = Math.abs(wk[i]);
			}
			//sort
			Arrays.sort(wk);
			for (int i = 0; i < wk.length; i++) {
				/*
				 *× 2 is
				 *・ Total total that should not be included in the total- wk[i]
				 *・ Further from the total sum without this value-Total total- wk[i] - wk[i]
				 */
				if (wk[i] > 0) {
					out.println(res - Math.abs(wk[i]) * 2);
					return;
				}
			}
		}

	}

D problem: DP solution

――I don't understand --Editorial I just tried to write

I'll write the contents of dp [] [] corresponding to input, but I don't understand the meaning. Let's come back after doing a typical dp contest.

[Note input value]

5
10 -4 -8 -11 3

i:0 / dp[i][0] : 0 / dp[i][1] : -2147483648
i:1 / dp[i][0] : 10 / dp[i][1] : -10
i:2 / dp[i][0] : 6 / dp[i][1] : 14
i:3 / dp[i][0] : 22 / dp[i][1] : 14
i:4 / dp[i][0] : 25 / dp[i][1] : 33
i:5 / dp[i][0] : 30 / dp[i][1] : 36
30
5
10 -4 -8 -11 9

i:0 / dp[i][0] : 0 / dp[i][1] : -2147483648
i:1 / dp[i][0] : 10 / dp[i][1] : -10
i:2 / dp[i][0] : 6 / dp[i][1] : 14
i:3 / dp[i][0] : 22 / dp[i][1] : 14
i:4 / dp[i][0] : 25 / dp[i][1] : 33
i:5 / dp[i][0] : 34 / dp[i][1] : 42
34
5
8 8 8 8 8

i:0 / dp[i][0] : 0 / dp[i][1] : -2147483648
i:1 / dp[i][0] : 8 / dp[i][1] : -8
i:2 / dp[i][0] : 16 / dp[i][1] : 0
i:3 / dp[i][0] : 24 / dp[i][1] : 8
i:4 / dp[i][0] : 32 / dp[i][1] : 16
i:5 / dp[i][0] : 40 / dp[i][1] : 24
40
5
-8 -8 -8 -8 -8

i:0 / dp[i][0] : 0 / dp[i][1] : -2147483648
i:1 / dp[i][0] : -8 / dp[i][1] : 8
i:2 / dp[i][0] : 16 / dp[i][1] : 0
i:3 / dp[i][0] : 8 / dp[i][1] : 24
i:4 / dp[i][0] : 32 / dp[i][1] : 16
i:5 / dp[i][0] : 24 / dp[i][1] : 40
24
	private void solveD3() {
		int numN = nextInt();
		long[] wk = LongStream.range(0, numN).map(i -> nextInt()).toArray();

		long[][] dp = new long[numN + 1][2];
		dp[0][0] = 0;
		dp[0][1] = Integer.MIN_VALUE;

		for (int i = 0; i < numN; i++) {
			dp[i + 1][0] = Long.max(dp[i][0] + wk[i], dp[i][1] - wk[i]);
			dp[i + 1][1] = Long.max(dp[i][0] - wk[i], dp[i][1] + wk[i]);
			out.println("i:" + i + " / dp[i][0] : " + dp[i][0] + " / dp[i][1] : " + dp[i][1]);
		}
		out.println("i:" + numN + " / dp[i][0] : " + dp[numN][0] + " / dp[i][1] : " + dp[numN][1]);
		out.println(dp[numN][0]);
	}

Recommended Posts

ABC --129- A & B & C & D
ABC --122 --A & B & C & D
ABC --125- A & B & C & D
ABC --130- A & B & C & D
ABC --126 --A & B & C & D
ABC --134- A & B & C & D & E
ABC --131- A & B & C & D & E
ABC --013-A & B & C
ABC --023 --A & B & C
ABC --036-A & B & C
ABC --010 --A & B & C
ABC --028 --A & B & C
ABC --015 --A & B & C
ABC --012-A & B & C
ABC --018 --A & B & C
ABC --054 --A & B & C
ABC --017 --A & B & C
ABC --029- A & B & C
ABC --019 --A & B & C
ABC --020 --A & B & C
ABC --030- A & B & C
ABC --127 --A & B & C
ABC --007 --A & B & C
ABC --132- A & B & C
ABC --026 --A & B & C
ABC --014- A & B & C
ABC --016 --A & B & C
ABC --011-A & B & C
ABC --031 --A & B & C
ABC --021 --A & B & C
ABC --025 --A & B & C
ABC --024 --A & B & C
ABC --027 --A & B & C
ABC --080- A & B & C
diverta 2019 Programming Contest A & B & C & D
AtCoder Beginner Contest 169 A, B, C with ruby
atcoder ABC113 C problem
atcoder ABC70 D problem
ABC093 C --Same Integers
atcoder ABC115 C problem
AtCoder Beginner Contest 170 A, B, C up to ruby
A person writing C ++ tried writing Java
Make a SOAP call in C #
Call a C function from Swift
What is a Ruby 2D array?
Convert Swift 2D array to C 2D array