This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#pragma GCC optimize("trapv")
#include <bits/stdc++.h>
using namespace std ;
struct Point
{
long long x , y ;
};
bool Is_Overflow(long long a , long long b)
{
if(a > 0 && (long long)(4e18) / a < b)
return true ;
else
return false ;
}
long long f(Point a , long long x)
{
if(Is_Overflow(x , a.x))
return (3e18 + 100) ;
else
return (x * a.x + a.y) ;
}
const long long inf = 3e18 ;
const int MAX = 2e5 + 10 ;
const int MAX2 = 1e7 + 10 ;
long long arr[MAX] ;
int n , m ;
long long x , t , w ;
vector< pair<long long , long long> >vp ;
long long val[MAX] , pref[MAX] ;
long long dp[MAX] ;
int L[MAX2] , R[MAX2] ;
Point Line[MAX2] ;
int id = 1 ;
void init()
{
for(int i = 1 ; i < MAX2 ; ++i)
Line[i].x = 0 , Line[i].y = inf ;
}
int Left(int node)
{
if(!L[node])
L[node] = ++id ;
return L[node] ;
}
int Right(int node)
{
if(!R[node])
R[node] = ++id ;
return R[node] ;
}
void Add_Line(Point p , int node = 1 , long long l = 0 , long long r = 1e12 + 100)
{
long long m = l + (r-l) / 2ll ;
bool lef = f(p , l) < f(Line[node] , l) ;
bool mid = f(p , m) < f(Line[node] , m) ;
if(mid)
swap(Line[node] , p) ;
if(r-l == 1)
return ;
if(lef != mid)
Add_Line(p , Left(node) , l , m) ;
else
Add_Line(p , Right(node) , m , r) ;
}
long long query(long long x , int node = 1 , long long l = 0 , long long r = 1e12 + 100)
{
long long m = l + (r-l) / 2ll ;
long long now = f(Line[node] , x) ;
if(r-l == 1)
return now ;
else if(x < m)
return min(now , query(x , Left(node) , l , m)) ;
else
return min(now , query(x , Right(node) , m , r)) ;
}
int main()
{
ios_base::sync_with_stdio(0) ;
cin.tie(0) ;
cin>>x>>n>>m>>w>>t ;
for(int i = 1 ; i <= n ; ++i)
cin>>arr[i] ;
for(int i = 1 ; i <= m ; ++i)
{
long long a , b ;
cin>>a>>b ;
vp.emplace_back(a , b) ;
}
vp.emplace_back(0 , 0) ;
sort(arr+1 , arr+n+1) ;
sort(vp.begin() , vp.end()) ;
for(int i = 1 ; i <= m ; ++i)
val[i] = inf , pref[i] = pref[i-1] + vp[i].second ;
arr[n+1] = x ;
for(int i = 1 ; i <= n+1 ; ++i)
{
int l = 1 , r = m ;
int idx = -1 ;
while(l <= r)
{
int mid = (l + r) >> 1 ;
if(arr[i] % t >= vp[mid].first)
idx = mid , l = mid+1 ;
else
r = mid-1 ;
}
if(idx != -1)
val[idx] = min(val[idx] , arr[i] / t) ;
}
Point p ;
p.x = 0 , p.y = 0 ;
Add_Line(p) ;
for(int i = 1 ; i <= m ; ++i)
{
dp[i] = dp[i-1] + x/t * w ;
if(x%t > vp[i].first)
dp[i] += w ;
if(val[i] != inf)
{
//dp[j] + pref[i] - pref[j] + (i-j) * val[i] * w
dp[i] = min(dp[i] , pref[i] + i * val[i] * w + query(val[i])) ;
//for(int j = i-1 ; j >= 0 ; --j)
// dp[i] = min(dp[i] , dp[j] + pref[i] - pref[j] + (i-j) * val[i] * w) ;
}
p.x = -i * w , p.y = dp[i] - pref[i] ;
Add_Line(p) ;
}
dp[m] += (x / t + 1) * w ;
return cout<<dp[m]<<"\n" , 0 ;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |