-
Notifications
You must be signed in to change notification settings - Fork 0
/
hayfeast.java
171 lines (135 loc) · 4.83 KB
/
hayfeast.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// This template code suggested by KT BYTE Computer Science Academy
// for use in reading and writing files for USACO problems.
// https://content.ktbyte.com/problem.java
//http://www.usaco.org/index.php?page=viewproblem2&cpid=767
//"Haybale Feast", 2017 December Gold Contest
import java.util.*;
import java.io.*;
public class hayfeast {
public static void main(String[] args) throws IOException {
String file = "hayfeast";
BufferedReader br = new BufferedReader(new FileReader(new File(file + ".in")));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
long M = Long.parseLong(st.nextToken());
int[] flavor = new int[N];
int[] spicy = new int[N];
for(int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
flavor[i] = Integer.parseInt(st.nextToken());
spicy[i] = Integer.parseInt(st.nextToken());
}
SegTreeMax tree = new SegTreeMax(N);
tree.buildTree(spicy);
br.close();
int result = Integer.MAX_VALUE;
int l = 0; //leftmost element of curr range
int r = 0; //rightmost element of curr range
long currFlavor = flavor[0];
while(l < N && r < N) {
if(currFlavor >= M) {
result = Math.min(result, tree.getMax(l, r));
}
if(l == r || currFlavor <= M) {
r++;
if(r < N) currFlavor += flavor[r];
} else {
currFlavor -= flavor[l];
l++;
}
}
PrintWriter out = new PrintWriter(new File(file + ".out"));
System.out.println(result);
out.println(result);
out.close();
}
public static class SegTreeMax {
//accept an integer array "A"
//build another array tree representing the segment tree
int[] tree; // tree array
int[] A; // original array of integers
int height; // height of the segment tree
int maxSize; // the size of the segment tree in its entirety
// (some nodes may have unused zeros)
int STARTINDEX = 0; // the left most range of any query
int ENDINDEX; // the right most range of any query
SegTreeMax(int n) {
A = new int[n];
Arrays.fill(A, Integer.MIN_VALUE);
height = (int) Math.ceil( Math.log(n)/Math.log(2) );
maxSize = (int) Math.pow(2, height+1) - 1; // 1 << height+1 - 1;
tree = new int[maxSize];
ENDINDEX = n - 1;
}
public int leftChild(int k) {return 2*k+1;}
public int rightChild(int k) {return 2*k+2;}
// build the whole segment tree [ O(n) ]
public void buildTree(int[] elements) {
for(int k=0; k<A.length; k++) {
A[k] = elements[k];
}
buildTree(STARTINDEX, ENDINDEX, 0);
}
// build the subtree (where root1 is the root) which represents [start, end]
private int buildTree(int low, int high, int currNode) {
if( low==high ) {
tree[currNode] = A[low];
} else {
int mid = (low + high)/2;
tree[currNode] = Math.max( buildTree(low, mid, leftChild(currNode))
, buildTree(mid + 1, high, rightChild(currNode)) );
}
return tree[currNode];
}
// find the max of A[x...y], inclusive
public int getMax(int x, int y) {
if(x < 0 || y >= A.length)
return Integer.MIN_VALUE;
return getMax(STARTINDEX, ENDINDEX, x, y, 0);
}
// find the max from x to y in the node
// [start, end]: range of current node
// [x, y]: query range
// currNode: ID of current node
private int getMax(int start, int end, int x, int y, int currNode) {
if( y < start || end < x ) // [x, y] contains [startIndex, endIndex]
return Integer.MIN_VALUE;
if( x <= start && end <= y ) // [x, y] doesn't overlap [startIndex, endIndex]
return tree[currNode];
// there is overlap between [start, end] and [low, high]
int mid = (start+end)/2;
int s1 = getMax(start, mid, x, y, leftChild(currNode));
int s2 = getMax(mid + 1, end, x, y, rightChild(currNode));
return Math.max(s1, s2);
}
// set value at position "loc" to "val": A[loc] = val
// (find the difference and update for all parent nodes!)
public void setValue(int loc, int val) {
int diff = val - A[loc];
setValue(STARTINDEX, ENDINDEX, loc, diff, 0);
}
// [start, end]: range of current node
// loc: position to be modified
// diff: the change to the specified position
private void setValue(int start, int end, int loc, int diff, int currNode) {
if( start==end ) { // leaf node
A[loc] += diff;
tree[currNode] += diff;
} else {
int mid = (start+end)/2;
if( start<=loc && loc<=mid ) { // loc is in the left child
setValue(start, mid, loc, diff, leftChild(currNode));
} else { // loc is in the right child
setValue(mid+1, end, loc, diff, rightChild(currNode));
}
tree[currNode] = Math.max(tree[leftChild(currNode)], tree[rightChild(currNode)]);
}
}
public void print() { //print all elements of tree
for(int i = 0; i < tree.length; i++) {
System.out.print(tree[i] + " " );
}
System.out.println();
}
}
}