written on 15 July 2023
Views : Loading...
Important problems are marked with *
Link: https://cses.fi/problemset/task/1621
You are given a list of $n$ integers, and your task is to calculate the number of distinct values in the list.
Solution:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
const ll mod = 1000000007;
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int t;cin>>t;
set<int>s;
while(t--){
int x;
cin>>x;
s.insert(x);
}
cout<<s.size();
return 0;
}
Link: https://cses.fi/problemset/task/1084
There are $n$ applicants and $m$ free apartments. Your task is to distribute the apartments so that as many applicants as possible will get an apartment.
Each applicant has a desired apartment size, and they will accept any apartment whose size is close enough to the desired size.
Solution:
int main()
{
fast;
int n,m,k;
cin>>n>>m>>k;
vector<int>a(n,0);
vector<int>b(m,0);
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<m;i++) cin>>b[i];
sort(a.begin(),a.end());
sort(b.begin(),b.end());
int i=0,j=0;
int count=0;
while(i<n && j<m){
if (a[i]-k>b[j])j++;
else if (a[i]+k<b[j])i++;
else{
count++;
i++;j++;
}
}
cout<<count<<endl;
return 0;
}
Link: https://cses.fi/problemset/task/1090
There are $n$ children who want to go to a Ferris wheel, and your task is to find a gondola for each child. Each gondola may have one or two children in it, and in addition, the total weight in a gondola may not exceed $x$. You know the weight of every child. What is the minimum number of gondolas needed for the children?
Solution:
signed main()
{
int n,x;
cin>>n>>x;
vector<int>a(n,0);
for(int i=0;i<n;i++) cin>>a[i];
sort(a.begin(),a.end());
int i=0,j=n-1;
int ans = 0;
while(i<j){
if (a[i]+a[j]>x){
ans++; j--;
}
else{
ans++;
i++;j--;
}
}
if (i==j) ans++;
cout<<ans<<endl;
return 0;
}
Link: https://cses.fi/problemset/task/1091
There are $n$ concert tickets available, each with a certain price. Then, $m$ customers arrive, one after another. Each customer announces the maximum price they are willing to pay for a ticket, and after this, they will get a ticket with the nearest possible price such that it does not exceed the maximum price.
Solution:
int check(int pos, vector<int> &replacement)
{
if (pos < 0)
return -1; // not found.
if (replacement[pos] == -2)
{
// found and unused ticket. next time a new ticket comes,
// we want to use the ticket at pos-1.
replacement[pos] = pos - 1;
return pos;
}
// otherwise keep searching till we find a ticket.
replacement[pos] = check(replacement[pos], replacement);
return replacement[pos];
}
signed main()
{
int n, m;
cin >> n >> m;
vector<int> tickets(n, 0), replacement(n, -2);
for (int i = 0; i < n; i++)
cin >> tickets[i];
sort(tickets.begin(), tickets.end());
while (m--)
{
int k;
cin >> k;
int pos = upper_bound(tickets.begin(), tickets.end(), k) - tickets.begin() - 1;
int index = check(pos, replacement);
if (index < 0)
cout << -1 << endl;
else
cout << tickets[index] << endl;
}
return 0;
}
Link: https://cses.fi/problemset/task/1619
You are given the arrival and leaving times of $n$ customers in a restaurant. What was the maximum number of customers in the restaurant at any time?
Solution:
def main():
l=[]
for _ in range(int(_input())):
a,b = map(int,_input().split())
l.append((a,1))
l.append((b,-1))
l.sort()
ans=0
x=0
for i in l:
x+=i[1]
ans=max(ans,x)
print(ans)
main()
Link: https://cses.fi/problemset/task/1629
In a movie festival, $n$ movies will be shown. You know the starting and ending time of each movie. What is the maximum number of movies you can watch entirely?
Solution:
def main():
l=[]
for _ in range(int(_input())):
a,b = map(int,_input().split())
l.append((a,b))
l = sorted(l,key=lambda x:x[1])
count=0
end_time=0
for i in l:
if end_time<=i[0]:
count+=1
end_time=i[1]
print(count)
main()
Link: https://cses.fi/problemset/task/1640/
You are given an array of $n$ integers, and your task is to find two values (at distinct positions) whose sum is $x$.
Solution:
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int n,x;
cin>>n>>x;
bool check = false;
map<int,int>m;
for(int i=1;i<=n;i++){
int k;
cin>>k;
int req = x-k;
if (m.find(req)==m.end()){
m[k]=i;
}
else{
cout<<i<<" "<<m[req];
check=true;
break;
}
}
if (!check) cout<<"IMPOSSIBLE";
return 0;
}
Link: https://cses.fi/problemset/task/1643
Given an array of $n$ integers, your task is to find the maximum sum of values in a contiguous, nonempty subarray.
Solution:
def main():
n=int(_input())
l = list(map(int,_input().split()))
if n==1: print(l[0])
else:
a=l[0]
b=float("-inf")
for i in range(1,n):
x = a+l[i]
if x>l[i]:
a=x
else: a=l[i]
b=max(b,a)
print(b)
main()
Link: https://cses.fi/problemset/task/1074
There are $n$ sticks with some lengths. Your task is to modify the sticks so that each stick has the same length. You can either lengthen or shorten each stick. Both operations cost $x$, where $x$ is the difference between the new and original length. What is the minimum total cost?
Solution:
def main():
n=int(_input())
l=sorted(list(map(int,_input().split())))
x = l[n//2]
ans=0
for i in l:
ans+=abs(x-i)
print(ans)
main()
Link: https://cses.fi/problemset/task/2183
You have $n$ coins with positive integer values. What is the smallest sum you cannot create using a subset of the coins?
Solution:
int main()
{
int n;
cin >> n;
vector<int> a(n, 0);
for (int i = 0; i < n; i++)
cin >> a[i];
sort(a.begin(), a.end());
if (a[0] != 1){
cout << 1 << endl;
return 0;
}
int cumulative_sum = 0;
for (int i = 0; i < n; i++){
cumulative_sum += a[i];
int k = cumulative_sum + 1;
if (i != n - 1){
if (a[i + 1] > k)
{
cout << k << endl;
return 0;
}
}
else
cout << k << endl;
}
return 0;
}
Link: https://cses.fi/problemset/task/2216
You are given an array that contains each number between 1…n exactly once. Your task is to collect the numbers from 1 to n in increasing order. On each round, you go through the array from left to right and collect as many numbers as possible. What will be the total number of rounds?
Solution:
def main():
n = int(_input())
l = list(map(int,_input().split()))
v = [0 for i in range(n+1)]
for i in range(n):
v[l[i]]=i
rounds = 0
for i in range(n):
if v[i]>v[i+1]:
rounds+=1
print(rounds+1)
main()
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int n,q;
cin>>n>>q;
vector<int> values(n+1);
vector<int> positions(n+1);
for(int i=1;i<n+1;i++){
cin>>values[i];
positions[values[i]]=i;
}
int ans=1;
for(int i=1;i<n;i++){
ans+=(positions[i]>positions[i+1]);
}
int l,r;
set < pair<int,int> > updated;
while(q--){
cin>>l>>r;
if (values[l]+1<=n){
updated.insert({values[l],values[l]+1});
}
if (values[l]-1>=1){
updated.insert({values[l]-1,values[l]});
}
if (values[r]+1<=n){
updated.insert({values[r],values[r]+1});
}
if (values[r]-1>=1){
updated.insert({values[r]-1,values[r]});
}
for(auto p:updated){
ans-=positions[p.first]>positions[p.second];
}
swap(values[l],values[r]);
positions[values[l]]=l;
positions[values[r]]=r;
for(auto p:updated){
ans+=positions[p.first]>positions[p.second];
}
cout<<ans<<endl;
updated.clear();
}
return 0;
}
You are given a playlist of a radio station since its establishment. The playlist has a total of $n$ songs. What is the longest sequence of successive songs where each song is unique?
Solution:
signed main()
{
int n;
cin>>n;
vector<int>songs(n,0);
map<int,int> last_seen;
map<int,int>::iterator itr;
int ans = 0;
int start = 0;
for(int end=0;end<n;end++){
int x;cin>>x;
itr = last_seen.find(x);
if (itr!=last_seen.end()){
start = max(start,last_seen[x]+1);
}
ans = max(ans,end-start+1);
last_seen[x]=end;
}
cout<<ans<<endl;
return 0;
}
Link: https://cses.fi/problemset/task/1073/
You are given $n$ cubes in a certain order, and your task is to build towers using them. Whenever two cubes are one on top of the other, the upper cube must be smaller than the lower cube.
You must process the cubes in the given order. You can always either place the cube on top of an existing tower or begin a new tower. What is the minimum possible number of towers?
Solution:
int main()
{
int n;
cin >> n;
vector<int> arr;
while (n--){
int k;
cin >> k;
auto it = upper_bound(arr.begin(), arr.end(), k);
if (it != arr.end()){
*it = k;
}
else{
arr.push_back(k);
}
}
cout << arr.size() << endl;
return 0;
}
Link: https://cses.fi/problemset/task/1163/
There is a street of length $x$ whose positions are numbered 0, 1, ..., $x$. Initially, there are no traffic lights, but $n$ sets of traffic lights are added to the street one after another. Your task is to calculate the length of the longest passage without traffic lights after each addition.
Solution:
signed main()
{
int x, n;
cin >> x >> n;
set<int> partitions;
multiset<int> lengths;
partitions.insert(0);
partitions.insert(x);
lengths.insert(x);
for (int i = 0; i < n; i++)
{
int p;
cin >> p;
partitions.insert(p);
auto itr = partitions.find(p);
int pre = *(prev(itr));
int nxt = *(next(itr));
auto itr1 = lengths.find(nxt - pre);
lengths.erase(itr1);
lengths.insert(p - pre);
lengths.insert(nxt - p);
cout << *(lengths.rbegin()) << " ";
}
return 0;
}
Link: https://cses.fi/problemset/task/2162
Consider a game where there are $n$ children (numbered 1, 2, ..., $n$) in a circle. During the game, every other child is removed from the circle until there are no children left. In which order will the children be removed?
Solution:
signed main()
{
int n;
cin >> n;
int cur_position = 0, step_size = 1, remaining_people = n, direction = 1;
while (cur_position + 1 <= n)
{
for (int i = cur_position + direction * step_size + 1; i <= n; i += 2 * step_size)
{
cout << i << " ";
}
int s = (remaining_people + 1 - direction) / 2;
cur_position += (1 - direction) * step_size;
step_size *= 2;
direction = (remaining_people + direction) % 2;
remaining_people -= s;
}
}
Link: https://cses.fi/problemset/task/2163/
Consider a game where there are $n$ children (numbered 1, 2, ..., $n$) in a circle. During the game, repeatedly $k$ children are skipped, and one child is removed from the circle. In which order will the children be removed?
Solution:
void findNextAlive(int cp, int tp, vector<int>& tree) {
tree[cp]--;
if (cp >= tree.size() / 2) {
cout << cp - (tree.size() / 2) + 1 << " ";
return;
}
if (tree[2 * cp] >= tp)
findNextAlive(2 * cp, tp, tree);
else
findNextAlive(2 * cp + 1, tp - tree[2 * cp], tree);
}
int main() {
int n, k;
cin >> n>>k;
int p = 0;
while ((1 << p) < n) p++;
int mx = 1 << p;
vector<int> tree(mx * 2, 0);
for (int i = 0; i < n; i++) {
tree[i + mx] = 1;
}
for (int i = mx - 1; i >= 1; i--)
tree[i] += tree[2 * i] + tree[2 * i + 1];
int pos = 0, length = n;
for (int i = 0; i < n; i++) {
int step = (k + 1) % length;
if (pos == 0 && step == 0) step = length;
pos += step;
if (pos > length) pos -= length;
findNextAlive(1, pos, tree);
pos--;
length--;
}
return 0;
}
Given n ranges, your task is to determine for each range if it contains some other range and if some other range contains it. Range [a,b] contains range [c,d] if a≤c and d≤b.
Solution:
struct range {
int l,r,index;
bool operator < (const range &other) const{
if (l==other.l){
return r>other.r;
}
return l<other.l;
}
};
int main()
{
int n; cin>>n;
if (n==2){
cout<<"1 0\n0 1";return 0;
}
vector<range> ranges(n);
vector<bool> contained(n);
vector<bool> contains(n);
for(int i=0;i<n;i++){
cin>>ranges[i].l;
cin>>ranges[i].r;
ranges[i].index=i;
}
sort(ranges.begin(),ranges.end());
int maxEnd = 0;
for(int i=0;i<n;i++){
if (ranges[i].r<=maxEnd){
contained[ranges[i].index]=true;
}
maxEnd = max(maxEnd,ranges[i].r);
}
int minEnd = 1e9;
for(int i=n-1;i>=0;i--){
if (ranges[i].r>=minEnd){
contains[ranges[i].index]=true;
}
minEnd = min(minEnd,ranges[i].r);
}
for(int i=0;i<n;i++){
cout<<contains[i]<<" ";
}
cout<<endl;
for(int i=0;i<n;i++){
cout<<contained[i]<<" ";
}
cout<<endl;
return 0;
}
There is a large hotel, and $n$ customers will arrive soon. Each customer wants to have a single room. You know each customer's arrival and departure day. Two customers can stay in the same room if the departure day of the first customer is earlier than the arrival day of the second customer. What is the minimum number of rooms that are needed to accommodate all customers? And how can the rooms be allocated?
Solution:
signed main()
{
int t;
cin >> t;
vector<pair<pair<int, int>, int>> customers(t);
for (int i = 0; i < t; i++)
{
cin >> customers[i].first.first >> customers[i].first.second;
customers[i].second = i;
}
sort(customers.begin(), customers.end());
vector<int> roomassignmed(t, -1);
int roomID = 1;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> rooms;
for (int i = 0; i < t; i++)
{
if (rooms.size() == 0)
{
roomassignmed[customers[i].second] = roomID++;
rooms.push(make_pair(customers[i].first.second, roomID - 1));
}
else
{
if (rooms.top().first < customers[i].first.first)
{
roomassignmed[customers[i].second] = rooms.top().second;
pair<int, int> x = rooms.top();
rooms.pop();
rooms.push(make_pair(customers[i].first.second, x.second));
}
else
{
roomassignmed[customers[i].second] = roomID++;
rooms.push(make_pair(customers[i].first.second, roomID - 1));
}
}
}
cout << roomID - 1 << endl;
for (int x : roomassignmed)
{
cout << x << " ";
}
return 0;
}
Link: https://cses.fi/problemset/task/1620
A factory has $n$ machines which can be used to make products. Your goal is to make a total of $t$ products. For each machine, you know the number of seconds it needs to make a single product. The machines can work simultaneously, and you can freely decide their schedule. What is the shortest time needed to make $t$ products?
Solution:
signed main()
{
int n, m;
cin >> n >> m;
vector<int> machines(n, 0);
for (int i = 0; i < n; i++)
cin >> machines[i];
int low = 1;
int high = 1e18;
int ans = 1e18;
while (low < high)
{
int mid = low + (high - low) / 2;
int products = 0;
for (int i = 0; i < n; i++){
int x = min(mid / machines[i], (int)1e18);
if (x+products<1e18) products+=x;
}
if (products >= m)
{
high = mid;
ans = min(ans, mid);
}
else
{
low = mid + 1;
}
}
cout << ans << endl;
return 0;
}
Link: https://cses.fi/problemset/task/1630/
You have to process $n$ tasks. Each task has a duration and a deadline, and you will process the tasks in some order one after another. Your reward for a task is $d-f$ where $d$ is its deadline and $f$ is your finishing time. (The starting time is 0, and you have to process all tasks even if a task would yield negative reward.) What is your maximum reward if you act optimally?
Solution:
int main()
{
int n; cin>>n;
vector< pair<int,int> > tasks;
for(int i=0;i<n;i++){
int a,b;
cin>>a>>b;
tasks.emplace_back(make_pair(a,b));
}
sort(tasks.begin(),tasks.end());
int time = 0;
int reward = 0;
for(int i=0;i<n;i++){
time+=tasks[i].first;
reward+=tasks[i].second - time;
}
cout<<reward<<endl;
return 0;
}
Link: https://cses.fi/problemset/task/1631/
There are $n$ books, and Kotivalo and Justiina are going to read them all. For each book, you know the time it takes to read it. They both read each book from beginning to end, and they cannot read a book at the same time. What is the minimum total time required?
Solution:
Proof:
Case 1: $T \geq S/2$
Case 2: $T < S/2$
By considering these two cases, we can see that the minimum time taken will be either $S$ or $2 \times T$, whichever is smaller. This is because if $T$ is greater than or equal to $S/2$, it is more efficient to read the books individually, resulting in a total time of $S$. On the other hand, if $T$ is less than $S/2$, it is more efficient to read the books simultaneously, resulting in a total time of $2 \times T$. Therefore, the minimum time taken can be calculated as $\min(2 \times T, S)$.
int main()
{
int n;cin>>n;
vector < int > books(n,0);
ll sum = 0;
ll largest_book=0;
for(int i=0;i<n;i++){
cin>>books[i];
sum+=books[i];
largest_book=max(largest_book,(ll)books[i]);
}
cout<<max(2*largest_book,sum);
return 0;
}
Link: https://cses.fi/problemset/task/1641
You are given an array of $n$ integers, and your task is to find three values (at distinct positions) whose sum is $x$.
Solution:
int main()
{
int n;ll x;
cin>>n>>x;
vector< pair<ll,int> > a(n);
for(int i=0;i<n;i++){
cin>>a[i].first;
a[i].second=i+1;
}
sort(a.begin(),a.end());
for(int i=0;i<n;i++){
ll x2 = x-a[i].first;
for(int j=i+1,k=n-1;j<k;j++){
while (a[j].first+a[k].first>x2) k--;
if(j<k && a[j].first+a[k].first==x2){
cout<<a[i].second<<" "<<a[j].second<<" "<<a[k].second;
return 0;
}
}
}
cout<<"IMPOSSIBLE";
return 0;
}
Link: https://cses.fi/problemset/task/1642/
You are given an array of $n$ integers, and your task is to find four values (at distinct positions) whose sum is $x$.
Solution:
int main()
{
int n,x;
cin>>n>>x;
vector<int> values(n);
for (int i = 0; i < n; i++){
cin>>values[i];
}
map<int,pair<int,int>>v2p;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
if (v2p.count(x-values[i]-values[j])){
cout<<i+1<<" "<<j+1<<" "<<v2p[x-values[i]-values[j]].first+1<<" "<<v2p[x-values[i]-values[j]].second+1;
return 0;
}
}
for(int j=0;j<i;j++){
v2p[values[i]+values[j]] = {i,j};
}
}
cout<<"IMPOSSIBLE";
return 0;
}
Link: https://cses.fi/problemset/task/1645/
Given an array of $n$ integers, your task is to find, for each array position, the nearest position to its left that has a smaller value.
Solution:
int main()
{
int n;
cin>>n;
vector<int> a(n,0);
for(int i=0;i<n;i++) cin>>a[i];
stack<int>s;
s.push(1);
cout<<0<<" ";
for(int i=1;i<n;i++){
while( !s.empty() && a[s.top()-1]>=a[i] ){
s.pop();
}
int pos;
if (s.empty()) pos=0;
else pos=s.top();
cout<<pos<<" ";
s.push(i+1);
}
return 0;
}
Link: https://cses.fi/problemset/task/1660/
Given an array of $n$ positive integers, your task is to count the number of subarrays that have a sum of $x$.
Solution:
int main()
{
int n,x;
cin>>n>>x;
vector<int> a(n,0);
for(int i=0;i<n;i++) cin>>a[i];
int window_sum = 0;
int l = 0;
int ans = 0;
for(int r=0;r<n;r++){
window_sum+=a[r];
while(l<r && window_sum>x){
window_sum-=a[l];
l++;
}
if (window_sum==x){
ans++;
}
}
cout<<ans<<endl;
return 0;
}
Link: https://cses.fi/problemset/task/1661/
Given an array of $n$ integers, your task is to count the number of subarrays that have a sum of $x$.
Solution:
signed main()
{
int n, x;
cin >> n >> x;
vector<int> a(n, 0);
for (int i = 0; i < n; i++)
cin >> a[i];
unordered_map<int, int> seen_prefix_sum;
int prefix_sum = 0;
seen_prefix_sum[prefix_sum] = 1;
int ans = 0;
for (int i = 0; i < n; i++)
{
prefix_sum += a[i];
int y = prefix_sum - x;
ans += seen_prefix_sum[y];
seen_prefix_sum[prefix_sum]++;
}
cout << ans << endl;
return 0;
}
Link: https://cses.fi/problemset/task/1662/
Given an array of n integers, your task is to count the number of subarrays where the sum of values is divisible by n.
Solution:
signed main()
{
int n;
cin >> n;
vector<int> a(n, 0);
for (int i = 0; i < n; i++)
cin >> a[i];
map<long long, int> seen_prefix_sum;
int prefix_sum = 0;
seen_prefix_sum[prefix_sum]++;
int ans = 0;
for (int i = 0; i < n; i++)
{
prefix_sum = (prefix_sum+a[i])%n;
if (prefix_sum<0) prefix_sum+=n;
ans+= seen_prefix_sum[prefix_sum];
seen_prefix_sum[prefix_sum]++;
}
cout << ans << endl;
return 0;
}
Link: https://cses.fi/problemset/task/2428
Given an array of n integers, your task is to calculate the number of subarrays that have at most k distinct values.
Solution:
int main()
{
int n,k; cin>>n>>k;
vector<int> values(n);
for(int i=0;i<n;i++) cin>>values[i];
ll ans=0;
map<int,int> seen;
int j=0;
for(int i=0;i<n;i++){
while(j<n && ( (int)seen.size()<k || seen.count(values[j])>0 )){
seen[values[j]]++;
j++;
}
ans+=j-i;
seen[values[i]]--;
if (seen[values[i]]==0){
seen.erase(values[i]);
}
}
cout<<ans;
return 0;
}
Link: https://cses.fi/problemset/task/1085
You are given an array containing n positive integers. Your task is to divide the array into k subarrays so that the maximum sum in a subarray is as small as possible.
Solution:
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int n;cin>>n;
int k;cin>>k;
vector < int > values(n,0);
int maxValue = 0;
for (int i = 0; i < n; i++)
{
cin>>values[i];
maxValue = max(maxValue,values[i]);
}
ll low = maxValue;
ll high = 1e18;
ll maximumSum = 1e18;
while(low<=high){
ll mid = (low+high)/2;
int blocks = 1;
ll sum=0;
for (int i = 0; i < n; i++)
{
if (sum+values[i]>mid){
sum=0;
blocks++;
}
sum+=values[i];
}
if (blocks>k){
low = mid+1;
}
else{
if (mid<maximumSum){
maximumSum=mid;
}
high =mid-1;
}
}
cout<<maximumSum;
return 0;
}
Link: https://cses.fi/problemset/task/1076/
You are given an array of $n$ integers. Your task is to calculate the median of each window of $k$ elements, from left to right. The median is the middle element when the elements are sorted. If the number of elements is even, there are two possible medians, and we assume that the median is the smaller of them.
Solution:
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
template<class T> using ordered_set =tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update> ;
signed main(){
ordered_set < pair<int,int> > s;
int n,k;
cin>>n>>k;
vector<int> nums(n,0);
for(int i=0;i<n;i++) cin>>nums[i];
for(int i=0;i<k;i++)
{
s.insert({nums[i],i});
}
cout<<(s.find_by_order((k-1)/2)->first)<<" ";
int j=0;
for(int i=k;i<n;i++)
{
s.erase({nums[j],j});
s.insert({nums[i],i});
cout<<(s.find_by_order((k-1)/2)->first)<<" ";
cout<<val<<" ";
j++;
}
return 0;
}
OR
void insert(int val, multiset<int>&low, multiset<int>&high,int &k){
int a = *low.rbegin(); // current median
if (a<val){
high.insert(val);
if (high.size()>k/2){
low.insert(*high.begin());
high.erase(high.find(*high.begin()));
}
} else {
low.insert(val);
if (low.size()>(k+1)/2){
high.insert(*low.rbegin());
low.erase(low.find(*low.rbegin()));
}
}
}
void erase(int val, multiset<int>&low, multiset<int>&high){
if (high.find(val) != high.end()) high.erase(high.find(val));
else low.erase(low.find(val));
if (low.empty()) {
low.insert(*high.begin());
high.erase(high.find(*high.begin()));
}
}
signed main()
{
multiset<int>low,high;
int n,k;
cin>>n>>k;
vector < int > a(n,0);
for (int i = 0; i < n; i++) cin>>a[i];
low.insert(a[0]);
for (int i = 1; i < k; i++) insert(a[i],low,high,k);
cout<<*low.rbegin()<<" ";
for (int i = k; i < n; i++) {
if (k==1){
insert(a[i],low,high,k);
erase(a[i-1],low,high);
}
else{
erase(a[i-k],low,high);
insert(a[i],low,high,k);
}
cout<<*low.rbegin()<<" ";
}
cout<<endl;
return 0;
}
Link: https://cses.fi/problemset/task/1077
You are given an array of n integers. Your task is to calculate for each window of k elements, from left to right, the minimum total cost of making all elements equal. You can increase or decrease each element with cost x where x is the difference between the new and the original value. The total cost is the sum of such costs.
Solution:
This problem is an extension of the previous problem.
Idea is to use 2 multisets for lower k/2 and upper k/2 elements.
We know that we have to change all the elements to the median of the window.
Hence we must find the sum distances of all the elements from the median.
we'll split the elements in the window into two groups and calculate the cost.
The smallest $K/2$ elements in the window will be in the lower group while the largest $K/2$ elements in the window will be in the upper group.
The cost of the window can be expressed as a function of $K,S_1,S_2$, and $M$, where $S_1$ and $S_2$ denote the sum of elements in the lower and upper group respectively, and $M$ denotes the median of the window.
The cost of the lower group will be $\sum_{i=1}^{K/2} M-e_i$, and the cost of the upper group will be $\sum_{i=1}^{K/2} e_i-M$, where $e$ represents an element in the group.
These expressions can be simplified to $M\times K/2 - S_1$ and $S_2 - M\times K/2$.
The total cost of the window is the sum of the costs contributed by both groups, or $S_2-S_1$.
void insert(int val, multiset<int>&low, multiset<int>&high,int &k,int &sum_high,int &sum_low){
int a = *low.rbegin(); // current median
if (a<val){
high.insert(val);
sum_high+=val;
if (high.size()>k/2){
sum_low+=*high.begin();
sum_high-=*high.begin();
low.insert(*high.begin());
high.erase(high.find(*high.begin()));
}
} else {
low.insert(val);
sum_low+=val;
if (low.size()>(k+1)/2){
sum_low-= *low.rbegin();
sum_high+= *low.rbegin();
high.insert(*low.rbegin());
low.erase(low.find(*low.rbegin()));
}
}
}
void erase(int val, multiset<int>&low, multiset<int>&high,int &sum_high,int &sum_low){
if (high.find(val) != high.end()) {high.erase(high.find(val)); sum_high-=val;}
else {low.erase(low.find(val)); sum_low-=val;}
if (low.empty()) {
sum_high-=*high.begin();
sum_low+=*high.begin();
low.insert(*high.begin());
high.erase(high.find(*high.begin()));
}
}
int med(int &k,multiset<int> &low){
return (k % 2 == 0) ? 0 : (*low.rbegin());
}
signed main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
multiset<int>low,high;
int n,k,sum_low=0,sum_high=0;
cin>>n>>k;
vector < int > a(n,0);
for (int i = 0; i < n; i++) cin>>a[i];
low.insert(a[0]);
sum_low+=a[0];
for (int i = 1; i < k; i++) insert(a[i],low,high,k,sum_high,sum_low);
cout<<sum_high-sum_low+med(k,low)<<" ";
for (int i = k; i < n; i++) {
if (k==1){
insert(a[i],low,high,k,sum_high,sum_low);
erase(a[i-1],low,high,sum_high,sum_low);
}
else{
erase(a[i-k],low,high,sum_high,sum_low);
insert(a[i],low,high,k,sum_high,sum_low);
}
cout<<sum_high-sum_low+med(k,low)<<" ";
}
cout<<endl;
return 0;
}
Link: https://cses.fi/problemset/task/1629
In a movie festival n movies will be shown. You know the starting and ending time of each movie. What is the maximum number of movies you can watch entirely?
Solution:
signed main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int n,k;
cin>>n>>k;
vector < pair<int,int > > v;
for (int i = 0; i < n; i++) {
int startTime,endTime; cin>>startTime>>endTime;
v.push_back(make_pair(endTime,startTime));
}
sort(v.begin(),v.end());
int ans = 0;
multiset<int> endTimes;
multiset<int>::iterator it;
for (int i = 0; i < k; i++) endTimes.insert(0);
for (int i = 0; i < n; i++) {
it = endTimes.upper_bound(v[i].second);
if (it==endTimes.begin()) continue;
endTimes.erase(prev(it));
endTimes.insert(v[i].first);
ans++;
}
cout<<ans;
return 0;
}
Link: https://cses.fi/problemset/task/1644
Given an array of n integers, your task is to find the maximum sum of values in a contiguous subarray with length between a and b.
Solution:
signed main()
{
int n,a,b;
cin>>n>>a>>b;
vector < int > prefix_sum(n+1);
for (int i = 1; i <= n; i++) {
int a; cin >> a;
prefix_sum[i] = a + prefix_sum[i - 1];
}
int ans = -1e18;
multiset<int> prefixes;
for (int i = a; i <= n; i++) {
if (i>b){
prefixes.erase(prefixes.find(prefix_sum[i-b-1]));
}
prefixes.insert(prefix_sum[i-a]);
ans = max(ans,prefix_sum[i]-*prefixes.begin());
}
cout<<ans;
return 0;
}