#pragma once
/**
* Author: Teetat T.
* Date: 2024-09-01
* Description: Max Plus Convolution. Find $C[k] = max_{i+j=k}\{A[i] + B[j]\}$.
* Time: $O(N)$.
*/// SMAWCK algorithm for finding row-wise maxima.// f(i,j,k) checks if M[i][j] <= M[i][k].// f(i,j,k) checks if M[i][k] is at least as good as M[i][j].// higher is better.template<classF>vector<int>smawck(constF&f,constvector<int>&rows,constvector<int>&cols){intn=(int)rows.size(),m=(int)cols.size();if(max(n,m)<=2){vector<int>ans(n,-1);for(inti=0;i<n;i++){for(intj:cols){if(ans[i]==-1||f(rows[i],ans[i],j)){ans[i]=j;}}}returnans;}if(n<m){// reducevector<int>st;for(intj:cols){while(true){if(st.empty()){st.emplace_back(j);break;}elseif(f(rows[(int)st.size()-1],st.back(),j)){st.pop_back();}elseif(st.size()<n){st.emplace_back(j);break;}else{break;}}}returnsmawck(f,rows,st);}vector<int>ans(n,-1);vector<int>new_rows;for(inti=1;i<n;i+=2){new_rows.emplace_back(rows[i]);}autores=smawck(f,new_rows,cols);for(inti=0;i<new_rows.size();i++){ans[2*i+1]=res[i];}for(inti=0,l=0,r=0;i<n;i+=2){if(i+1==n)r=m;while(r<m&&cols[r]<=ans[i+1])r++;ans[i]=cols[l++];for(;l<r;l++){if(f(rows[i],ans[i],cols[l])){ans[i]=cols[l];}}l--;}returnans;}template<classF>vector<int>smawck(constF&f,intn,intm){vector<int>rows(n),cols(m);iota(rows.begin(),rows.end(),0);iota(cols.begin(),cols.end(),0);returnsmawck(f,rows,cols);}// Max Plus Convolution.// b must be convex, i.e. b[i]-b[i-1]>=b[i+1]-b[i].template<classT>vector<T>max_plus_convolution_arbitary_convex(vector<T>a,constvector<T>&b){if(a.empty()||b.empty())return{};if((int)b.size()==1){for(auto&x:a)x+=b[0];returna;}intn=(int)a.size(),m=(int)b.size();autof=[&](inti,intj){returna[j]+b[i-j];};autocmp=[&](inti,intj,intk){if(i<k)returnfalse;if(i-j>=m)returntrue;returnf(i,j)<=f(i,k);};autobest=smawck(cmp,n+m-1,n);vector<T>ans(n+m-1);for(inti=0;i<n+m-1;i++){ans[i]=f(i,best[i]);}returnans;}
#line 2 "src/convolution/max-plus-convolution.hpp"
/**
* Author: Teetat T.
* Date: 2024-09-01
* Description: Max Plus Convolution. Find $C[k] = max_{i+j=k}\{A[i] + B[j]\}$.
* Time: $O(N)$.
*/// SMAWCK algorithm for finding row-wise maxima.// f(i,j,k) checks if M[i][j] <= M[i][k].// f(i,j,k) checks if M[i][k] is at least as good as M[i][j].// higher is better.template<classF>vector<int>smawck(constF&f,constvector<int>&rows,constvector<int>&cols){intn=(int)rows.size(),m=(int)cols.size();if(max(n,m)<=2){vector<int>ans(n,-1);for(inti=0;i<n;i++){for(intj:cols){if(ans[i]==-1||f(rows[i],ans[i],j)){ans[i]=j;}}}returnans;}if(n<m){// reducevector<int>st;for(intj:cols){while(true){if(st.empty()){st.emplace_back(j);break;}elseif(f(rows[(int)st.size()-1],st.back(),j)){st.pop_back();}elseif(st.size()<n){st.emplace_back(j);break;}else{break;}}}returnsmawck(f,rows,st);}vector<int>ans(n,-1);vector<int>new_rows;for(inti=1;i<n;i+=2){new_rows.emplace_back(rows[i]);}autores=smawck(f,new_rows,cols);for(inti=0;i<new_rows.size();i++){ans[2*i+1]=res[i];}for(inti=0,l=0,r=0;i<n;i+=2){if(i+1==n)r=m;while(r<m&&cols[r]<=ans[i+1])r++;ans[i]=cols[l++];for(;l<r;l++){if(f(rows[i],ans[i],cols[l])){ans[i]=cols[l];}}l--;}returnans;}template<classF>vector<int>smawck(constF&f,intn,intm){vector<int>rows(n),cols(m);iota(rows.begin(),rows.end(),0);iota(cols.begin(),cols.end(),0);returnsmawck(f,rows,cols);}// Max Plus Convolution.// b must be convex, i.e. b[i]-b[i-1]>=b[i+1]-b[i].template<classT>vector<T>max_plus_convolution_arbitary_convex(vector<T>a,constvector<T>&b){if(a.empty()||b.empty())return{};if((int)b.size()==1){for(auto&x:a)x+=b[0];returna;}intn=(int)a.size(),m=(int)b.size();autof=[&](inti,intj){returna[j]+b[i-j];};autocmp=[&](inti,intj,intk){if(i<k)returnfalse;if(i-j>=m)returntrue;returnf(i,j)<=f(i,k);};autobest=smawck(cmp,n+m-1,n);vector<T>ans(n+m-1);for(inti=0;i<n+m-1;i++){ans[i]=f(i,best[i]);}returnans;}