Problem:
F - Dangerous Delivery / 危険な輸送
Story
Dのひとは重大な使命を背負っていた。それはDAtaCoDer社長のDhokudai氏へ、次のDAtaCoDer Regular Contest(DARC)のD問題を届けることだ。Dのひとのアジトがある都市
1
からDAtaCoDer本社がある都市
N
までは
N
個の都市が一直線に並んでいる。この移動の間、不正を企む緑の三角形の集団がD問題を狙っており、その魔の手からD問題を守らねばならない。
幸い、Dのひとは次元(ディメンジョン)の壁を超えて移動する能力を持っているため、簡単に捕まるようなことはない。しかしこの移動法にはいくつかの欠点がある。第一に、移動を開始する際には隙ができてしまい、またその瞬間が見つかると、移動先までバレてしまう。緑の三角形達はそれぞれが複数の都市を見渡せるように監視し続けている。しかもDのひとの移動を読み、少しずつ都市
N
の方向へ移動しているようだ。よって、多くの緑の三角形達に監視されている都市からの移動や、長い距離の移動は発見のリスクが高まってしまう。また第二の欠点として、次元の壁を超える移動は体への負担がかかるため、
1
日に
1
度しか使えない。次のDARCが開催される
D
日後までに間に合わせるよう、ペース配分を考える必要もある。緑の三角形ごときにDのひとが捕捉されることなどまずありえないが、慎重派であるDのひとは、
D
日後までに都市
1
から都市
N
に移動するためのリスクを最小化しようと考えた。
Problem
二次元平面上に
N
個の都市がある。都市
1
から
N
は左から右へ一直線上に並んでおり、都市
i
は位置
(p_i,0)
にある。
p_i<p_{i+1}
(
1 \leq i < N
)を満たす。
また、この二次元平面上には
M
人の敵がおり、敵
j
は当初、位置
(a_j,b_j)
にいる。敵
j
は左方向について、上下
45
°の範囲を見張っている。すなわち、直線
y=x-a_j+b_j
以上で、かつ、直線
y=-x+a_j+b_j
以下の領域に含まれる全ての都市が視界に入っている。また、すべての敵は
1
日ごとにちょうど
X
だけ右方向に移動する。すなわち、
d
日目の敵
j
の位置は
(a_j+X(d-1),b_j)
である。
ここで、
d
日目における都市
i
の監視度
w_{d,i}
は、
d
日目において都市
i
を視界に入れている敵の総数により定義される。このとき、
d
日目の都市
i
から都市
k
への移動は、
w_{d,i} \times |p_i-p_k|
のリスクを負う。
1
日に
1
度しか移動できないとするとき、
D
日後までに都市
1
から都市
N
まで移動する際のリスクの総和を最小化せよ。
Input
入力は以下の形式からなる。
N
M
D
X
p_1
p_2
...
p_N
a_1
b_1
...
a_M
b_M
1
行目は
4
つの整数からなり、都市の数
N
、敵の数
M
、移動にかけてよい日数の上限
D
、
1
日ごとの敵の移動距離
X
がそれぞれ空白
1
文字区切りで与えられる。
2
行目は
N
個の整数からなり、
i
番目の整数は都市
i
の位置の
x
座標
p_i
が空白
1
文字区切りで与えられる。 続く
M
行は敵の位置情報が与えられる。
j+2
行目(
1 \leq j \leq M
)は
2
つの整数からなり、敵
j
の
1
日目の位置の
x
座標
a_j
、
y
座標
b_j
が空白
1
文字区切りで与えられる。
制約:
1 \leq N \leq 10^4
1 \leq M \leq 10^4
1 \leq D \leq 10^2
1 \leq X \leq 10^6
0 \leq p_i, a_j \leq 10^6, -10^6 \leq b_j \leq 10^6
p_i<p_{i+1}
Output
D
日目までに都市
N
にいるためのリスクの総和の最小値を
1
行に出力せよ。行の最後では必ず改行を行うこと。
Sample Input 1
3 2 2 1
0 3 6
1 1
3 -2
Sample Output 1
6
1日目、都市1は2人、都市2は0人、都市3は0人に監視されている。 2日目も同様に、都市1は2人、都市2は0人、都市3は0人に監視されている。 よって、1日目に都市1から都市2に移動してリスクが
2 \times |3-0|=6
、2日目に都市2から都市3へ移動してリスクが
0 \times |6-3|=0
の合計6が最小である。
Sample Input 2
3 2 2 1
0 3 6
2 1
3 -1
Sample Output 2
9
移動の仕方は1つ目のサンプルと同じだが、2日目は敵の移動により都市2の監視人数が1人増えるため、コストが
1 \times |6-3|=3
に変化する。 よって、最小リスクは9である。
Sample Input 3
10 8 5 3
0 8 10 13 17 20 21 29 30 45
18 2
50 -20
17 1
38 21
40 -11
0 0
0 0
22 -1
Sample Output 3
222

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;

using VS = vector<string>;    using LL = long long;
using VI = vector<int>;       using VVI = vector<VI>;
using PII = pair<int, int>;   using PLL = pair<LL, LL>;
using VL = vector<LL>;        using VVL = vector<VL>;

#define ALL(a)  begin((a)),end((a))
#define RALL(a) (a).rbegin(), (a).rend()
#define SZ(a) int((a).size())
#define SORT(c) sort(ALL((c)))
#define RSORT(c) sort(RALL((c)))
#define UNIQ(c) (c).erase(unique(ALL((c))), end((c)))
#define FOR(i, s, e) for (int(i) = (s); (i) < (e); (i)++)
#define FORR(i, s, e) for (int(i) = (s); (i) > (e); (i)--)
#define debug(x) cerr << #x << ": " << x << endl
const int INF = 1e9;                          const LL LINF = 1e16;
const LL MOD = 1000000007;                    const double PI = acos(-1.0);
int DX[8] = { 0, 0, 1, -1, 1, 1, -1, -1 };    int DY[8] = { 1, -1, 0, 0, 1, -1, 1, -1 };

/* -----  2018/06/30  Problem: AOJ 2580 / Link: http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2580  ----- */
/* ------問題------

二次元平面上にN個の都市がある。都市1からNは左から右へ一直線上に並んでおり、都市iは位置(pi,0)にある。pi<pi+1 (1≤i<N)を満たす。
また、この二次元平面上にはM人の敵がおり、敵jは当初、位置(aj,bj)にいる。敵jは左方向について、上下45°の範囲を見張っている。すなわち、直線 y=x−aj+bj 以上で、かつ、直線y=−x+aj+bj 以下の領域に含まれる全ての都市が視界に入っている。また、すべての敵は1日ごとにちょうどXだけ右方向に移動する。すなわち、d日目の敵jの位置は(aj+X(d−1),bj)である。
ここで、d日目における都市iの監視度wd,iは、d日目において都市iを視界に入れている敵の総数により定義される。このとき、d日目の都市iから都市kへの移動は、wd,i×|pi−pk|のリスクを負う。1日に1度しか移動できないとするとき、D日後までに都市1から都市Nまで移動する際のリスクの総和を最小化せ

-----問題ここまで----- */
/* -----解説等-----

DP + CHT(live performanceと一緒の形)で、
O(DN^2) -> O(DNlogN+DM+N)で解ける。
まず位置はD回情報を作るとする。この位置からW_di的なものを作るが、これはsortすれば二分探索とかimos方で監視している緑のアレの数がわかる。
あとは愚直DPを式変形して、dpのseedもCHTの定数項に打ち込めば良い。(ここがlive performanceと一緒)
よって解けた。
単調CHTと速度比較をしたが同じ速度だった。

----解説ここまで---- */

struct LiChao_min {
	struct line {
		LL m, c;
		line(LL _m = 0, LL _c = 0) { m = _m; c = _c; }
		LL eval(LL x) { return m * x + c; }
	};
	struct node {
		node *l, *r; line f;
		node(line v) { f = v; l = r = NULL; }
	};
	typedef node* pnode;
	pnode root; int sz;
#define mid ((l+r)>>1)
	void insert(line &v, int l, int r, pnode &nd) {
		if (!nd) { nd = new node(v); return; }
		LL trl = nd->f.eval(l), trr = nd->f.eval(r);
		LL vl = v.eval(l), vr = v.eval(r);
		if (trl <= vl && trr <= vr) return;
		if (trl > vl && trr > vr) { nd->f = v; return; }
		if (trl > vl) swap(nd->f, v);
		if (nd->f.eval(mid) < v.eval(mid)) insert(v, mid + 1, r, nd->r);
		else swap(nd->f, v), insert(v, l, mid, nd->l);
	}
	LL query(int x, int l, int r, pnode &nd) {
		if (!nd) return LLONG_MAX;
		if (l == r) return nd->f.eval(x);
		if (mid >= x) return min(nd->f.eval(x), query(x, l, mid, nd->l));
		return min(nd->f.eval(x), query(x, mid + 1, r, nd->r));
	}
	/* -sz <= query_x <= sz */
#undef mid
	void init(int _sz) { sz = _sz + 1; root = NULL; }
	void add_line(LL m, LL c) { line v(m, c); insert(v, -sz, sz, root); }
	LL query(LL x) { return query(x, -sz, sz, root); }
};


int abs(int x) {
	return x < 0 ? -x : x;
}
int main() {
	cin.tie(0);
	ios_base::sync_with_stdio(false);

	int N, M, D, X;
	cin >> N >> M >> D >> X;
	VL p(N);
	FOR(i, 0, N) {
		cin >> p[i];
	}
	VL xs(M);
	FOR(i, 0, M) {
		int x, y; cin >> x >> y;
		x -= abs(y);
		xs[i] = x;
	}
	VVL imosD(D);
	FOR(d, 0, D) {
		vector<PLL>za;
		FOR(i, 0, N) {
			za.push_back(PLL(p[i], 0));
		}
		FOR(i, 0, M) {
			za.push_back(PLL(xs[i] + X*d, 1));
		}
		SORT(za);
		VL imos(N + 1, 0);
		int Stacksize = 0;
		int cityidx = 0;
		FOR(i, 0, SZ(za)) {
			if (za[i].second == 0) {
				imos[cityidx++] -= Stacksize;
				Stacksize = 0;
			}
			else {
				if (cityidx) {
					imos[0]++;
					Stacksize++;
				}
			}
		}
		FOR(i, 0, N) {
			imos[i + 1] += imos[i];
		}
		imosD[d] = imos;
	}

	VVL dp(D + 1, VL(N, LINF));
	dp[0][0] = 0;
	FOR(d, 0, D) {
		LiChao_min CHT; CHT.init(1e6 + 1e2);
		FOR(i, 0, N) {
			if (CHT.root != NULL)
				dp[d + 1][i] = min(dp[d+1][i] , CHT.query(p[i]));
			dp[d + 1][i] = min(dp[d + 1][i], dp[d][i]);
			CHT.add_line(imosD[d][i], -imosD[d][i] * p[i] + dp[d][i]);
		}
	}
	cout << dp[D][N - 1] << endl;


	return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 19540
final_rank: 12

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 998244353
//#define MOD 1000000007
#define EPS 0.000000001



#define SIZE 10005


ll N,M,D;
ll X;
ll POS[SIZE];
ll A[SIZE],B[SIZE];
ll rui[105][SIZE];
ll min_dist[105][SIZE];


double calc(ll day,int ind){

	ll p = A[ind] + X*(day-1);
	ll q = B[ind];

	if(B[ind] == 0){

		return p;

	}else if(B[ind] > 0){

		return p-q;

	}else{ //B[ind] < 0

		return p+q;
	}
}

int main(){

	cin >> N >> M >> D >> X;

	if(N == 1){

		printf("0\n");
		return 0;
	}

	for(ll i = 0; i < N; i++){

		scanf("%lld",&POS[i]);
	}

	for(int i = 0; i < M; i++){

		scanf("%lld %lld",&A[i],&B[i]);
		for(ll d = 1; d <= D; d++){
			ll x = calc(d,i);

			int loc = upper_bound(POS,POS+N,x)-POS;
			loc--;

			if(loc < 0)continue;

			rui[d][loc]++;
		}
	}

	for(int d = 1; d <= D; d++){
		for(int a = N-2; a >= 0; a--){

			rui[d][a] += rui[d][a+1];
		}
	}

	for(int d = 1; d <= D+1; d++){
		for(int i = 0; i < N; i++){

			min_dist[d][i] = HUGE_NUM;
		}
	}

	min_dist[1][0] = 0;


	ll ans = HUGE_NUM;

	for(int from = 0; from < N-1; from++){
		for(int d = 1; d <= D; d++){
			if(min_dist[d][from] == HUGE_NUM)continue;

			if(d >= 2 && min_dist[d][from] >= min_dist[d-1][from])continue;

			for(int next = from+1; next < N; next++){
				ll tmp_cost = min_dist[d][from]+rui[d][from]*(POS[next]-POS[from]);

				chmin(min_dist[d+1][next],tmp_cost);
			}
			chmin(ans,min_dist[d+1][N-1]);
		}
	}

	printf("%lld\n",ans);

	return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 19192
final_rank: 13

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 998244353
//#define MOD 1000000007
#define EPS 0.000000001



#define SIZE 10005


ll N,M,D;
ll X;
ll POS[SIZE];
ll A[SIZE],B[SIZE];
ll rui[105][SIZE];
ll min_dist[105][SIZE];


double calc(ll day,int ind){

	ll p = A[ind] + X*(day-1);
	ll q = B[ind];

	if(B[ind] == 0){

		return p;

	}else if(B[ind] > 0){

		return p-q;

	}else{ //B[ind] < 0

		return p+q;
	}
}

int main(){

	cin >> N >> M >> D >> X;

	if(N == 1){

		printf("0\n");
		return 0;
	}

	for(ll i = 0; i < N; i++){

		scanf("%lld",&POS[i]);
	}

	for(int i = 0; i < M; i++){

		//printf("\n i:%d\n",i);

		scanf("%lld %lld",&A[i],&B[i]);
		for(ll d = 1; d <= D; d++){
			ll x = calc(d,i);

			int loc = upper_bound(POS,POS+N,x)-POS;
			loc--;

			if(loc < 0)continue;

			//printf("x:%lld loc:%d date:%lld\n",x,loc,d);

			rui[d][loc]++;
		}
	}

	for(int d = 1; d <= D; d++){
		for(int a = N-2; a >= 0; a--){

			rui[d][a] += rui[d][a+1];
		}
	}

	/*for(int d = 1; d <= D; d++){
		printf("\n %d日目\n",d);
		for(int a = 0; a < N; a++){

			printf("都市[%d]:%lld\n",a,rui[d][a]);
		}
	}*/


	for(int d = 1; d <= D+1; d++){
		for(int i = 0; i < N; i++){

			min_dist[d][i] = HUGE_NUM;
		}
	}

	min_dist[1][0] = 0;


	ll ans = HUGE_NUM;

	for(int from = 0; from < N-1; from++){
		for(int d = 1; d <= D; d++){
			if(min_dist[d][from] == HUGE_NUM)continue;

			if(d >= 2 && min_dist[d][from] >= min_dist[d-1][from])continue;

			for(int next = from+1; next < N; next++){
				ll tmp_cost = min_dist[d][from]+rui[d][from]*(POS[next]-POS[from]);

				chmin(min_dist[d+1][next],tmp_cost);
			}
			chmin(ans,min_dist[d+1][N-1]);
		}
	}

	/*for(ll day = 1; day <= D; day++){

		for(int k = day-1; k < N; k++){

			min_dist[next][k] = HUGE_NUM;
		}
		for(int from = day-1; from < N; from++){
			if(min_dist[now][from] == HUGE_NUM)continue;

			for(int to = from+1; to < N; to++){
				ll next_dist = min_dist[now][from]+rui[day][from]*abs(POS[from]-POS[to]);
				chmin(min_dist[next][to],next_dist);
			}
		}
		chmin(ans,min_dist[next][N-1]);
		swap(now,next);
	}*/

	printf("%lld\n",ans);

	return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 19196
final_rank: 14

code_snippet: #include <bits/stdc++.h>
//#include <atcoder/all>
//using namespace atcoder;
#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")
using namespace std;
 
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef pair<int, int> pii;
typedef pair<long long, long long> PLL;
typedef pair<int, PII> TIII;
 
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
 
 
#define FOR(i, s, n) for (int i = s; i < (int)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define rep(i, a, b) for (int i = a; i < (b); ++i)
#define trav(a, x) for (auto &a : x)
#define all(x) x.begin(), x.end()
 
#define MOD 1000000007
 
template<class T1, class T2> inline bool chmax(T1 &a, T2 b) {if (a < b) {a = b; return true;} return false;}
template<class T1, class T2> inline bool chmin(T1 &a, T2 b) {if (a > b) {a = b; return true;} return false;}
const double EPS = 1e-8, PI = acos(-1);
const double pi = 3.141592653589793238462643383279;
//ここから編集    
typedef string::const_iterator State;
ll GCD(ll a, ll b){
  return (b==0)?a:GCD(b, a%b);
}
ll LCM(ll a, ll b){
  return a/GCD(a, b) * b;
}
template< int mod >
struct ModInt {
  int x;
 
  ModInt() : x(0) {}
 
  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
 
  ModInt &operator+=(const ModInt &p) {
    if((x += p.x) >= mod) x -= mod;
    return *this;
  }
 
  ModInt &operator-=(const ModInt &p) {
    if((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
 
  ModInt &operator*=(const ModInt &p) {
    x = (int) (1LL * x * p.x % mod);
    return *this;
  }
 
  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }
 
  ModInt operator-() const { return ModInt(-x); }
 
  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }
 
  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }
 
  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }
 
  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }
 
  bool operator==(const ModInt &p) const { return x == p.x; }
 
  bool operator!=(const ModInt &p) const { return x != p.x; }
 
  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while(b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
 
  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while(n > 0) {
      if(n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }
 
  friend ostream &operator<<(ostream &os, const ModInt &p) {
    return os << p.x;
  }
 
  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt< mod >(t);
    return (is);
  }
 
  static int get_mod() { return mod; }
};
 
using modint = ModInt< 998244353 >;
template< typename T >
struct Combination {
  vector< T > _fact, _rfact, _inv;
 
  Combination(int sz) : _fact(sz + 1), _rfact(sz + 1), _inv(sz + 1) {
    _fact[0] = _rfact[sz] = _inv[0] = 1;
    for(int i = 1; i <= sz; i++) _fact[i] = _fact[i - 1] * i;
    _rfact[sz] /= _fact[sz];
    for(int i = sz - 1; i >= 0; i--) _rfact[i] = _rfact[i + 1] * (i + 1);
    for(int i = 1; i <= sz; i++) _inv[i] = _rfact[i] * _fact[i - 1];
  }
 
  inline T fact(int k) const { return _fact[k]; }
 
  inline T rfact(int k) const { return _rfact[k]; }
 
  inline T inv(int k) const { return _inv[k]; }
 
  T P(int n, int r) const {
    if(r < 0 || n < r) return 0;
    return fact(n) * rfact(n - r);
  }
 
  T C(int p, int q) const {
    if(q < 0 || p < q) return 0;
    return fact(p) * rfact(q) * rfact(p - q);
  }
 
  T H(int n, int r) const {
    if(n < 0 || r < 0) return (0);
    return r == 0 ? 1 : C(n + r - 1, r);
  }
};
 
ll modpow(ll x, ll n, ll mod) {
  ll res = 1;
  x %= mod;
  if(x == 0) return 0;
  while(n) {
    if(n&1) res = (res * x) % mod;
    x = (x * x) % mod;
    n >>= 1;
  }
  return res;
} 
inline long long mod(long long a, long long m) {
    return (a % m + m) % m;
}
template<typename T> 
struct BIT{
  int N;
  std::vector<T> node;
  BIT(){}
  BIT(int n){
    N = n;
    node.resize(N+10);
  }
  void build(int n) {
    N = n;
    node.resize(N+10);
  }
  /* a: 1-indexed */
  void add(int a, T x){
    for(int i=a; i<(int)node.size(); i += i & -i) node[i] += x;
  }

  /* [1, a] */
  T sum(int a){
    T res = 0;
    for(int x=a; x>0; x -= x & -x) res += node[x];
    return res;
  }

  /* [l, r] */
  T rangesum(int l, int r){
    return sum(r) - sum(l-1);
  }

  /* 
    a1+a2+...+aw >= valとなるような最小のwを返す
    @verify https://codeforces.com/contest/992/problem/E
  */
  int lower_bound(T val) {
    if(val < 0) return 0;

    int res = 0;
    int n = 1; 
    while (n < N) n *= 2;

    T tv=0;
    for (int k = n; k > 0; k /= 2) {
      if(res + k < N && node[res + k] < val){
        val -= node[res+k];
        res += k;
      }
    }
    return res+1; 
  }
};
struct UnionFind{
  std::vector<int> par;
  std::vector<int> siz;

  UnionFind(int sz_): par(sz_), siz(sz_) {
    for(int i=0; i<sz_; ++i) par[i] = i, siz[i] = 1;
  }

  void init(int sz_){
    par.resize(sz_);
    siz.resize(sz_);
    for(int i=0; i<sz_; ++i) par[i] = i, siz[i] = 1;
  }

  int root(int x){
    if(x == par[x]) return x;
    return par[x] = root(par[x]);
  }

  bool merge(int x, int y){
    x = root(x), y = root(y);
    if(x == y) return false;
    if(siz[x] < siz[y]) std::swap(x, y);
    siz[x] += siz[y];
    par[y] = x;
    return true;
  }

  bool issame(int x, int y){
    return root(x) == root(y);
  }

  int size(int x){
    return siz[root(x)];
  }
};
struct RollingHash{

    using ull = unsigned long long;
    const ull mod = (1ULL << 61) - 1;
    const ull MASK30 = (1ULL << 30) - 1;
    const ull MASK31 = (1ULL << 31) - 1;

    const ull MASK61 = mod;

    ull base;
    int n;
    vector<ull> hash, pow;

    RollingHash(const string &s)
    {
        random_device rnd;
        mt19937_64 mt(rnd());
        base = 1001;
        
        n = (int)s.size();
        hash.assign(n+1, 0);
        pow.assign(n+1, 1);
        
        for(int i=0; i<n; i++){
            hash[i+1] = calc_mod(mul(hash[i], base) + s[i]);
            pow[i+1] = calc_mod(mul(pow[i], base));
        }
    }

    ull calc_mod(ull x){
        ull xu = x >> 61;
        ull xd = x & MASK61;
        ull res = xu + xd;
        if(res >= mod) res -= mod;
        return res;
    }

    ull mul(ull a, ull b){
        ull au = a >> 31;
        ull ad = a & MASK31;
        ull bu = b >> 31;
        ull bd = b & MASK31;
        ull mid = ad * bu + au * bd;
        ull midu = mid >> 30;
        ull midd = mid & MASK30;
        return calc_mod(au * bu * 2 + midu + (midd << 31) + ad * bd);
    }

    //[l,r)のハッシュ値
    inline ull get(int l, int r){
        ull res = calc_mod(hash[r] + mod*3-mul(hash[l], pow[r-l]));
        return res;
    }
    //string tのハッシュ値
    inline ull get(string t){
        ull res = 0;
        for(int i=0; i<t.size(); i++){
            res = calc_mod(mul(res, base)+t[i]);
        }
        return res;
    }
    //string s中のtの数をカウント
    inline int count(string t) {
        if(t.size() > n) return 0;
        auto hs = get(t);
        int res = 0;
        for(int i=0; i<n-t.size()+1; i++){
            if(get(i, i+t.size()) == hs) res++; 
        }
        return res;
    }

    /* 
        concat 
        @verify https://codeforces.com/problemset/problem/514/C
    */
    inline ull concat(ull h1, ull h2, int h2len){
      return calc_mod(h2 + mul(h1, pow[h2len]));
    }

    // LCPを求める S[a:] T[b:]
    inline int LCP(int a, int b){
        int len = min((int)hash.size()-a, (int)hash.size()-b);
        
        int lb = -1, ub = len;
        while(ub-lb>1){
            int mid = (lb+ub)/2;

            if(get(a, a+mid) == get(b, b+mid)) lb = mid;
            else ub = mid;
        }
        return lb;
    }
};
struct ConvexHullTrick {
  struct Line{
    ll x, y;
    Line(): x(0), y(0){}
    Line(ll _x, ll _y): x(_x), y(_y){}
    bool operator < (const Line &l) const {
      return (x != l.x) ? x < l.x : y < l.y;
    }
  }; 
  vector<Line> lv;
  function<bool(ll l, ll r)> comp;
  
  ConvexHullTrick(function<bool(ll l, ll r)> _comp = [](ll l, ll r){ return l <= r; }): comp(_comp) {}

  bool check(Line& l1, Line& l2, Line &l3){
    if(l1 < l3) swap(l1, l3);
    return (l2.y-l1.y)*(l3.x-l2.x) <= (l3.y-l2.y)*(l2.x-l1.x);
  }
  void add(ll a, ll b) {
    Line l = {a, b};
    while(lv.size()>=2 && check(lv[lv.size()-2], lv.back(), l)) lv.pop_back();
    lv.push_back(l);
  }
  ll f(ll id, ll x){
    return lv[id].x * x + lv[id].y;
  }
  ll query(ll x){
    if(lv.empty()) return LLONG_MAX;
    ll low = -1, high = lv.size() - 1;
    while (high - low > 1) {
      ll mid = (high + low) / 2;
      (comp(f(mid, x), f(mid + 1, x)) ? low : high) = mid;
    }
    return f(high, x);
  }
};
ll dp[110][10101];
int main() {  
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(12);
  
  ll N, M, D, X; cin >> N >> M >> D >> X;
  vector<ll> p(N);
  REP(i,N) cin >> p[i];

  vector<ll> a(M), b(M);
  REP(i,M) cin >> a[i] >> b[i];
  REP(i,110) REP(j,10101) dp[i][j] = (1LL<<60);
  dp[0][0] = 0;
  REP(i,D) {
    vector<int> cnt(N+1);
    REP(j,M) {
      ll x = a[j] + X * i, y = b[j];
      ll lb = -1, ub = N;
      while(ub-lb>1) {
        ll mid = (ub+lb)/2;
        
        if(x < p[mid]) ub = mid;
        else{
          if(-p[mid]+x+y >= 0 && p[mid]-x+y <= 0) lb = mid;
          else ub = mid;
        }
      }
      cnt[0]++;
      cnt[lb+1]--;
    }
    
    REP(j,N) cnt[j+1] += cnt[j];

    ConvexHullTrick cht([](ll l, ll r){return l >= r;});
    for(int j=0; j<N; j++) { 
      if(dp[i][j] != (1LL<<60))cht.add(cnt[j], dp[i][j]-p[j]*cnt[j]);
    }
    for(int j=0; j<N; j++) {
      dp[i+1][j] = min(dp[i+1][j], cht.query(p[j]));
    }
 
  }
  ll ans = (1LL<<60);
  REP(i,D+1) ans = min(ans, dp[i][N-1]);
  cout << dp[D][N-1] << endl;
  return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 12424
final_rank: 7

code_snippet: /**
 * @brief ユーザ定義リテラル
 * @author えびちゃん
 */

#ifndef H_int_literals
#define H_int_literals

#include <cstddef>
#include <cstdint>

constexpr intmax_t  operator ""_jd(unsigned long long n) { return n; }
constexpr uintmax_t operator ""_ju(unsigned long long n) { return n; }
constexpr size_t    operator ""_zu(unsigned long long n) { return n; }
constexpr ptrdiff_t operator ""_td(unsigned long long n) { return n; }

#endif  /* !defined(H_int_literals) */

/**
 * @brief 多次元 vector の作成
 * @author えびちゃん
 */

#ifndef H_make_vector
#define H_make_vector

#include <cstddef>
#include <type_traits>
#include <vector>

namespace detail {
  template <typename Tp, size_t N>
  std::vector<Tp> make_vector(
      std::vector<size_t>& sizes,
      typename std::enable_if<(N == 1), Tp const&>::type x
  ) {
    return std::vector<Tp>(sizes[0], x);
  }
  template <typename Tp, size_t N>
  auto make_vector(
      std::vector<size_t>& sizes,
      typename std::enable_if<(N > 1), Tp const&>::type x
  ) {
    size_t size = sizes[N-1];
    sizes.pop_back();
    return std::vector<decltype(make_vector<Tp, N-1>(sizes, x))>(
        size, make_vector<Tp, N-1>(sizes, x)
    );
  }
}  // detail::

template <typename Tp, size_t N>
auto make_vector(size_t const(&sizes)[N], Tp const& x = Tp()) {
  std::vector<size_t> s(N);
  for (size_t i = 0; i < N; ++i) s[i] = sizes[N-i-1];
  return detail::make_vector<Tp, N>(s, x);
}

#endif  /* !defined(H_make_vector) */

/**
 * @brief ラムダ式の再帰
 * @author えびちゃん
 */

#ifndef H_make_fix_point
#define H_make_fix_point

#include <utility>

template <typename Fn>
class fix_point: Fn {
public:
  explicit constexpr fix_point(Fn&& f) noexcept: Fn(std::forward<Fn>(f)) {}

  template <typename... Args>
  constexpr decltype(auto) operator ()(Args&&... args) const {
    return Fn::operator ()(*this, std::forward<Args>(args)...);
  }
};

template <typename Fn>
static inline constexpr decltype(auto) make_fix_point(Fn&& f) noexcept {
  return fix_point<Fn>{std::forward<Fn>(f)};
}

#endif  /* !defined(H_make_fix_point) */

#include <cstdio>
#include <cstdint>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <utility>
#include <tuple>

template <typename Fn>
auto monotone_minima(Fn&& f, size_t h, size_t w) {
  using value_type = decltype(f(h, w));
  std::vector<size_t> res(h);

  make_fix_point([&](auto dfs, size_t hl, size_t hu, size_t wl, size_t wu) -> void {
      if (hl >= hu) return;
      size_t hm = (hl+hu) >> 1;
      value_type min = f(hm, wl);
      res[hm] = wl;
      for (size_t j = wl+1; j < wu; ++j) {
        value_type cur = f(hm, j);
        if (cur < min) {
          min = std::move(cur);
          res[hm] = j;
        }
      }
      if (hl == hm) return;
      dfs(hl, hm, wl, res[hm]+1);
      dfs(hm+1, hu, res[hm], wu);
  })(0, h, 0, w);
  return res;
}

int main() {
  size_t n, m, d;
  intmax_t x;
  scanf("%zu %zu %zu %jd", &n, &m, &d, &x);

  std::vector<intmax_t> p(n);
  for (auto& pi: p) scanf("%jd", &pi);

  std::vector<intmax_t> q(m);
  for (auto& qi: q) {
    intmax_t a, b;
    scanf("%jd %jd", &a, &b);
    qi = a - std::abs(b);
  }

  intmax_t const inf = 1e18;
  intmax_t res = inf;
  auto dp = make_vector({n}, inf);
  dp[0] = 0;
  for (size_t dd = 0; dd < d; ++dd) {
    std::vector<intmax_t> w(n+1, 0);
    w[0] = m;
    for (auto const& qi: q) {
      size_t i = std::upper_bound(p.begin(), p.end(), qi) - p.begin();
      --w[i];
    }
    for (size_t i = 1; i <= n; ++i) w[i] += w[i-1];

    auto tmp = make_vector({n}, inf);

    auto f = [&](size_t i, size_t j) -> intmax_t {
      if (!(j < i)) return inf;
      return dp[j] + w[j] * (p[i]-p[j]);
    };
    auto prev = monotone_minima(f, n, n);

    for (size_t i = 0; i < n; ++i)
      tmp[i] = f(i, prev[i]);

    dp = std::move(tmp);
    res = std::min(res, dp[n-1]);
    for (auto& qi: q) qi += x;
  }

  printf("%jd\n", res);
}
accuracy: 1
time_ms: 40
memory_kb: 3036
final_rank: 1

code_snippet: #include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

using ll = long long;
using Pll = pair<ll, ll>;

constexpr ll INF = 1LL << 60;

class ConvexHullTrick {
    public:
    int n = 0;
    deque<Pll> lines;
    
    ConvexHullTrick() {}

    bool check(Pll line1, Pll line2, Pll line3) {
        return (line3.second-line2.second)*(line1.first-line2.first) > (line2.second-line1.second)*(line2.first-line3.first);
    }

    // 直線の傾きの降順に直線が与えられる前提
    void add(ll grad, ll intercept) {
        while(n >= 2 && !check(lines[n-2], lines[n-1], {grad, intercept})) {
            lines.pop_back();
            --n;
        }
        lines.emplace_back(grad, intercept);
        ++n;
    }

    ll f(ll i, ll x) {
        return lines[i].first*x + lines[i].second;
    }

    ll get_min(ll x) {
        while(n > 1 && f(0, x) >= f(1, x)) {
            lines.pop_front();
            --n;
        }
        return f(0, x);
    }
};

int main() {
    int N, M, D, X;
    cin >> N >> M >> D >> X;
    vector<ll> p(N);
    for(int i=0;i<N;++i) cin >> p[i];

    vector<ll> lines(M);
    ll a, b;
    for(int i=0;i<M;++i) {
        cin >> a >> b;
        if(b > 0) {
            lines[i] = a-b-X;
        } else {
            lines[i] = a+b-X;
        }
    }
    sort(lines.begin(), lines.end());

    vector<vector<ll>> w(D, vector<ll>(N, 0));
    for(int d=0;d<D;++d) {
        int li = 0;
        for(int i=0;i<N;++i) {
            while(li < M && X*(d+1)+lines[li] < p[i]) ++li;
            w[d][i] = M-li;
        }
    }

    vector<vector<ll>> dp(D+1, vector<ll>(N, INF));
    dp[0][0] = 0;
    for(int d=1;d<=D;++d) {
        ConvexHullTrick cht = ConvexHullTrick();
        for(int i=0;i<N;++i) {
            if(dp[d-1][i] != INF) cht.add(w[d-1][i], dp[d-1][i]-w[d-1][i]*p[i]);
            dp[d][i] = cht.get_min(p[i]);
        }
    }

    cout << dp[D][N-1] << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 18728
final_rank: 11

code_snippet: #include <cstdio>
#include <cstdint>
#include <cassert>
#include <vector>
#include <algorithm>
#include <utility>
#include <string>
#include <deque>
#include <tuple>
#include <map>

bool mie(intmax_t x, intmax_t y, intmax_t p) {
  if (x < p) return false;
  intmax_t yl = y - (x-p);
  intmax_t yu = y + (x-p);
  return (yl <= 0 && 0 <= yu);
}

template <typename Tp>
class lines {
  // assuming monotonicity
  std::deque<std::pair<Tp, Tp>> lines;

public:
  void append(Tp a, Tp b) {
    if (lines.empty()) {
      lines.emplace_back(a, b);
      return;
    }

    Tp a0, b0, a1, b1;
    std::tie(a1, b1) = lines.back();
    while (lines.size() > 1) {
      std::tie(a0, b0) = lines[lines.size()-2];
      if ((a1-a)*(b1-b0) < (a0-a1)*(b-b1)) break;
      lines.pop_back();
      a1 = a0;
      b1 = b0;
    }
    lines.emplace_back(a, b);
  }

  Tp min_at(Tp x) {
    Tp a0, b0, a1, b1;
    std::tie(a0, b0) = lines[0];
    while (lines.size() > 1) {
      std::tie(a1, b1) = lines[1];
      if (a0*x+b0 < a1*x+b1) break;
      lines.pop_front();
      a0 = a1;
      b0 = b1;
    }
    Tp a, b;
    std::tie(a, b) = lines[0];
    return a*x + b;
  }
};

int main() {
  size_t N, M, D;
  intmax_t X;
  scanf("%zu %zu %zu %jd", &N, &M, &D, &X);

  std::vector<intmax_t> p(N);
  for (auto& pi: p) scanf("%jd", &pi);

  std::vector<intmax_t> a(M), b(M);
  for (size_t i = 0; i < M; ++i)
    scanf("%jd %jd", &a[i], &b[i]);

  std::vector<std::vector<int>> w(D, std::vector<int>(N+1));
  for (size_t i = 0; i < M; ++i) {
    // i 番目の敵
    intmax_t x = a[i] - X;
    intmax_t y = b[i];
    for (size_t j = 0; j < D; ++j) {
      // j 日目
      x += X;
      if (!mie(x, y, p[0])) continue;

      ++w[j][0];
      {
        size_t lb = 0;
        size_t ub = N;
        while (ub-lb > 1) {
          size_t mid = (lb+ub) >> 1;
          (mie(x, y, p[mid])? lb: ub) = mid;
        }
        --w[j][ub];
      }
    }
  }

  for (size_t i = 0; i < D; ++i)
    for (size_t j = 1; j <= N; ++j)
      w[i][j] += w[i][j-1];

  intmax_t inf = 1e12;
  std::vector<std::vector<intmax_t>> dp(D+1, std::vector<intmax_t>(N, inf));
  dp[0][0] = 0;
  for (size_t i = 1; i <= D; ++i) {
    lines<intmax_t> ll;
    for (size_t j = 1; j < N; ++j) {
      size_t k = j-1;
      ll.append(w[i-1][k], dp[i-1][k]-w[i-1][k]*p[k]);
      dp[i][j] = ll.min_at(p[j]);
    }
  }

  intmax_t res = inf;
  for (size_t i = 0; i <= D; ++i)
    res = std::min(res, dp[i][N-1]);

  printf("%jd\n", res);
}
accuracy: 1
time_ms: 40
memory_kb: 14604
final_rank: 8

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef pair<ll,ll> mp;
#define inf 1e9
typedef pair<mp,ll> mmp; // cost day next
ll w(ll d,ll j,ll x,vector<ll> &p,vector<mp> &a){
    ll res = 0;
    for(int i=0;i<a.size();i++){
	 if( p[j] <=  a[i].first + x*(d-1) - abs(a[i].second) ) res ++ ;
	 //cout<<p[i]<<' '<<a[i].first + x*(d-1)-abs(a[i].second )<<endl;
    }
    return res;
}

int main(){
	ll n,m,d,x;
	cin>>n>>m>>d>>x;
	vector<ll> p(n);
	for(int i=0;i<n;i++) cin>>p[i];
	vector<mp> a(m);
	for(int i=0;i<m;i++)cin>>a[i].first>>a[i].second;
	//vector<vector<bool> > used(n,vector<bool>(d+1,false) );
	vector<ll> dp(n,(ll)inf);
	priority_queue<mmp,vector<mmp>,greater<mmp> > q;
	q.push(mmp(mp(0,0),0 ) );
	dp[0] = 0;
	while(!q.empty()){
	    mmp now = q.top();
	    q.pop();
	    ll nn = now.second;
	    ll day = now.first.first;
	    ll cost = now.first.second;
	  //  cout<<nn<<' '<<day<<' '<<cost<<endl;
	    /*if(nn == n-1){
		cout<<cost<<endl;
		break;
	    }*/
	   // if( dp[nn] <= cost) continue;
	    //if(used[nn][day])continue;
	    //used[nn][day] = true;
	    ll W = w(day+1,nn,x,p,a);
	//    cout<<W<<endl;
	    for(int i=nn+1;i<n;i++){
		//if(used[i][day+1] ) continue;
		if(day >= d)continue;
		ll nc = cost + W*(abs(p[i]-p[nn]) ); 
		if(dp[i] <= nc)continue;
		dp[i] = nc;
		q.push(mmp( mp(day+1 ,nc ),i ) );
	    }
	}
	cout<<dp[n-1]<<endl;
	return 0;
}
accuracy: 0.3548387096774194
time_ms: 10
memory_kb: 3224
final_rank: 17

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef pair<ll,ll> mp;
#define inf 1e9
typedef pair<mp,ll> mmp; // cost day next
ll w(int d,int j,int x,vector<int> &p,vector<mp> &a){
    ll res = 0;
    for(int i=0;i<a.size();i++){
	 if( p[j] <=  a[i].first + x*(d-1) - abs(a[i].second) ) res ++ ;
	 //cout<<p[i]<<' '<<a[i].first + x*(d-1)-abs(a[i].second )<<endl;
    }
    return res;
}

int main(){
	int n,m,d,x;
	cin>>n>>m>>d>>x;
	vector<int> p(n);
	for(int i=0;i<n;i++) cin>>p[i];
	vector<mp> a(m);
	for(int i=0;i<m;i++)cin>>a[i].first>>a[i].second;
	vector<vector<bool> > used(n,vector<bool>(d+1,false) );
	priority_queue<mmp,vector<mmp>,greater<mmp> > q;
	q.push(mmp(mp(0,0),0 ) );
	while(!q.empty()){
	    mmp now = q.top();
	    q.pop();
	    ll nn = now.second;
	    ll day = now.first.second;
	    ll cost = now.first.first;
	  //  cout<<nn<<' '<<day<<' '<<cost<<endl;
	    if(nn == n-1){
		cout<<cost<<endl;
		break;
	    }
	    if(used[nn][day])continue;
	    used[nn][day] = true;
	    ll W = w(day+1,nn,x,p,a);
	//    cout<<W<<endl;
	    for(int i=nn+1;i<n;i++){
		if(used[i][day+1] ) continue;
		if(day > d)continue;
		q.push(mmp( mp(cost + W*( abs(p[i] - p[nn] ) ) , day+1 ),i ) );
	    }
	}
	return 0;
}
accuracy: 0.07526881720430108
time_ms: 10
memory_kb: 9140
final_rank: 20

code_snippet: #include <bits/stdc++.h>

using namespace std;
using ll = long long;
// #define int ll
using PII = pair<ll, ll>;

#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()

template<typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template<typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }
template<typename T> bool IN(T a, T b, T x) { return a<=x&&x<b; }
template<typename T> T ceil(T a, T b) { return a/b + !!(a%b); }

template<typename T> vector<T> make_v(size_t a) { return vector<T>(a); }
template<typename T,typename... Ts>
auto make_v(size_t a,Ts... ts) {
    return vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));
}
template<typename T,typename V> typename enable_if<is_class<T>::value==0>::type
fill_v(T &t, const V &v) { t=v; }
template<typename T,typename V> typename enable_if<is_class<T>::value!=0>::type
fill_v(T &t, const V &v ) { for(auto &e:t) fill_v(e,v); }

template<class S,class T>
ostream &operator <<(ostream& out,const pair<S,T>& a) {
    out<<'('<<a.first<<','<<a.second<<')'; return out;
}
template<class T>
ostream &operator <<(ostream& out,const vector<T>& a){
    out<<'[';
    for(const T &i: a) out<<i<<',';
    out<<']';
    return out;
}
template<class T>
ostream &operator <<(ostream& out, const set<T>& a) {
    out<<'{';
    for(const T &i: a) out<<i<<',';
    out<<'}';
    return out;
}
template<class T, class S>
ostream &operator <<(ostream& out, const map<T,S>& a) {
    out<<'{';
    for(auto &i: a) out<<i<<',';
    out<<'}';
    return out;
}

int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0}; // DRUL
const int INF = 1<<30;
const ll LLINF = 1LL<<60;
const ll MOD = 1000000007;

// 単調性なしok 動的CHT 各操作O(logN)
template <typename T, const T id = numeric_limits<T>::min()>
class ConvexHullTrick {
private:
    struct line {
        T a, b;
        line(T a_ = 0, T b_ = 0) : a(a_), b(b_) {}
        T get(T x) { return a * x + b; }
    };
    struct node {
        line l;
        node *lch, *rch;
        node(line l_) : l(l_), lch(nullptr), rch(nullptr) {}
    };

    const T minx, maxx;
    node *root = nullptr;

    // [lb, ub]
    node* update(node *p, ll lb, ll ub, line& l) {
        if (!p) return new node(l);
        if (p->l.get(lb) >= l.get(lb) && p->l.get(ub) >= l.get(ub)) return p;
        if (p->l.get(lb) <= l.get(lb) && p->l.get(ub) <= l.get(ub)) {
          p->l = l;
          return p;
        }
        ll mid = (lb + ub) / 2;
        if (p->l.get(mid) < l.get(mid)) swap(p->l, l);
        if (p->l.get(lb) <= l.get(lb)) p->lch = update(p->lch, lb, mid, l);
        else p->rch = update(p->rch, mid + 1, ub, l);
        return p;
    }
    // [lb, ub]
    T query(node *p, ll lb, ll ub, ll t) const {
        if(!p) return id;
        if(ub == lb) return p->l.get(t);
        ll mid = (lb+ub)/2;
        if(t <= mid) return max(p->l.get(t), query(p->lch, lb, mid, t));
        return max(p->l.get(t), query(p->rch, mid + 1, ub, t));
    }
public:
    // getで呼び出しうるxの範囲を指定
    ConvexHullTrick(const T minx_, const T maxx_) : minx(minx_), maxx(maxx_) {}
    // 直線ax+bを追加 最小がほしければ-ax-bを渡してgetの結果に×(-1)する
    void insert(T a, T b) {
        line l(a, b);
        root = update(root, minx, maxx, l);
    }
    // ax+b のうち最大のものを返す
    T get(T x) const { return query(root, minx, maxx, x); }
};

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2580
namespace aoj2580 {
    ll dp[105][10010];
    void solve() {
        ll n, m, d, x;
        cin >> n >> m >> d >> x;
        vector<ll> p(n), a(m), b(m);
        REP(i, n) cin >> p[i];
        REP(i, m) cin >> a[i] >> b[i];

        REP(i, d) REP(j, n) dp[i][j] = LLINF;

        {
            ll num = 0;
            REP(j, m) {
                ll pos;
                if(b[j] >= 0) {
                    pos = a[j]-b[j];
                } else {
                    pos = a[j]+b[j];
                }
                if(pos >= p[0]) num++;
                a[j] += x;
            }
            REP(i, n) dp[0][i] = num * (p[i] - p[0]);
        }

        FOR(i, 1, d) {
            vector<ll> num(n);
            REP(j, m) {
                ll pos;
                if(b[j] >= 0) {
                    pos = a[j]-b[j];
                } else {
                    pos = a[j]+b[j];
                }
                ll tmp = upper_bound(ALL(p), pos) - p.begin() - 1;
                if(tmp >= 0) num[tmp]++;
                a[j] += x;
            }
            for(ll j=n-2; j>=0; --j) num[j] += num[j+1];

            ConvexHullTrick<ll> cht(0, 1000000010);
            REP(j, n) {
                cht.insert(-num[j], -dp[i-1][j]+num[j]*p[j]);
                dp[i][j] = -cht.get(p[j]);
            }
        }

        ll ret = LLINF;
        REP(i, d) chmin(ret, dp[i][n-1]);
        cout << ret << endl;
    }
}

// https://codeforces.com/contest/311/problem/B
namespace cf185div1B {
    ll d[100010], t[100010], T[100010], dp[105][100010];
    void solve() {
        ll n, m, p;
        cin >> n >> m >> p;
        REP(i, n-1) cin >> d[i+1];
        REP(i, n-1) d[i+1] += d[i];
        REP(i, m) {
            ll a, b;
            cin >> a >> b;
            t[i] = (b-d[a-1]);
        }
        sort(t, t+m);
        T[0] = t[0];
        REP(i, m-1) T[i+1] += T[i] + t[i+1];

        REP(i, m) dp[0][i] = (i+1)*t[i] - T[i];
        FOR(i, 1, p) {
            ConvexHullTrick<ll> cht(-1000000010, 1000000010);
            dp[i][0] = t[0] - T[0];
            cht.insert(0, dp[i-1][0] + T[0]);
            FOR(j, 1, m) {
                dp[i][j] = -cht.get(t[j]) + t[j]*j - T[j];
                cht.insert(j, -dp[i-1][j]-T[j]);
            }
        }

        cout << dp[p-1][m-1] << endl;
    }
}

signed main(void)
{
    cin.tie(0);
    ios::sync_with_stdio(false);

    aoj2580::solve();
    // cf185div1B::solve();

    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 11604
final_rank: 5

code_snippet: #include <bits/stdc++.h>

using namespace std;
using ll = long long;
// #define int ll
using PII = pair<ll, ll>;

#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()

template<typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template<typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }
template<typename T> bool IN(T a, T b, T x) { return a<=x&&x<b; }
template<typename T> T ceil(T a, T b) { return a/b + !!(a%b); }

template<typename T> vector<T> make_v(size_t a) { return vector<T>(a); }
template<typename T,typename... Ts>
auto make_v(size_t a,Ts... ts) {
    return vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));
}
template<typename T,typename V> typename enable_if<is_class<T>::value==0>::type
fill_v(T &t, const V &v) { t=v; }
template<typename T,typename V> typename enable_if<is_class<T>::value!=0>::type
fill_v(T &t, const V &v ) { for(auto &e:t) fill_v(e,v); }

template<class S,class T>
ostream &operator <<(ostream& out,const pair<S,T>& a) {
    out<<'('<<a.first<<','<<a.second<<')'; return out;
}
template<class T>
ostream &operator <<(ostream& out,const vector<T>& a){
    out<<'[';
    for(const T &i: a) out<<i<<',';
    out<<']';
    return out;
}
template<class T>
ostream &operator <<(ostream& out, const set<T>& a) {
    out<<'{';
    for(const T &i: a) out<<i<<',';
    out<<'}';
    return out;
}
template<class T, class S>
ostream &operator <<(ostream& out, const map<T,S>& a) {
    out<<'{';
    for(auto &i: a) out<<i<<',';
    out<<'}';
    return out;
}

int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0}; // DRUL
const int INF = 1<<30;
const ll LLINF = 1LL<<60;
const ll MOD = 1000000007;

// 単調性なしok 動的CHT 各操作O(logN)
template <typename T, const T id = numeric_limits<T>::min()>
class ConvexHullTrick {
private:
    struct line {
        T a, b;
        line(T a_ = 0, T b_ = 0) : a(a_), b(b_) {}
        T get(T x) { return a * x + b; }
    };
    struct node {
        line l;
        node *lch, *rch;
        node(line l_) : l(l_), lch(nullptr), rch(nullptr) {}
    };

    const T minx, maxx;
    node *root = nullptr;

    // [lb, ub]
    node* update(node *p, int lb, int ub, line& l) {
        if (!p) return new node(l);
        if (p->l.get(lb) >= l.get(lb) && p->l.get(ub) >= l.get(ub)) return p;
        if (p->l.get(lb) <= l.get(lb) && p->l.get(ub) <= l.get(ub)) {
          p->l = l;
          return p;
        }
        int mid = (lb + ub) / 2;
        if (p->l.get(mid) < l.get(mid)) swap(p->l, l);
        if (p->l.get(lb) <= l.get(lb)) p->lch = update(p->lch, lb, mid, l);
        else p->rch = update(p->rch, mid + 1, ub, l);
        return p;
    }
    // [lb, ub]
    T query(node *p, int lb, int ub, int t) const {
        if(!p) return id;
        if(ub == lb) return p->l.get(t);
        int mid = (lb+ub)/2;
        if(t <= mid) return max(p->l.get(t), query(p->lch, lb, mid, t));
        return max(p->l.get(t), query(p->rch, mid + 1, ub, t));
    }
public:
    // xの範囲
    ConvexHullTrick(const T minx_, const T maxx_) : minx(minx_), maxx(maxx_) {}
    // 直線ax+bを追加 最小がほしければ-ax-bを渡してgetの結果に×(-1)する
    void insert(T a, T b) {
        line l(a, b);
        root = update(root, minx, maxx, l);
    }
    // ax+b のうち最大のものを返す
    T get(T x) const { return query(root, minx, maxx, x); }
};


// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2580
namespace aoj2580 {
    ll dp[105][10010];
    void solve() {
        ll n, m, d, x;
        cin >> n >> m >> d >> x;
        vector<ll> p(n), a(m), b(m);
        REP(i, n) cin >> p[i];
        REP(i, m) cin >> a[i] >> b[i];

        REP(i, d) REP(j, n) dp[i][j] = LLINF;

        {
            ll num = 0;
            REP(j, m) {
                ll pos;
                if(b[j] >= 0) {
                    pos = a[j]-b[j];
                } else {
                    pos = a[j]+b[j];
                }
                if(pos >= p[0]) num++;
                a[j] += x;
            }
            REP(i, n) dp[0][i] = num * (p[i] - p[0]);
        }

        FOR(i, 1, d) {
            vector<ll> num(n);
            REP(j, m) {
                ll pos;
                if(b[j] >= 0) {
                    pos = a[j]-b[j];
                } else {
                    pos = a[j]+b[j];
                }
                ll tmp = upper_bound(ALL(p), pos) - p.begin() - 1;
                if(tmp >= 0) num[tmp]++;
                a[j] += x;
            }
            for(ll j=n-2; j>=0; --j) num[j] += num[j+1];
            // cout << num << endl;

            ConvexHullTrick<ll> cht(0, 1000010);
            REP(j, n) {
                cht.insert(-num[j], -dp[i-1][j]+num[j]*p[j]);
                dp[i][j] = -cht.get(p[j]);
            }
        }

        // REP(i, d) {
        //     REP(j, n) cout << dp[i][j] << " ";
        //     cout << endl;
        // }
        ll ret = LLINF;
        REP(i, d) chmin(ret, dp[i][n-1]);
        cout << ret << endl;
    }
}

// https://codeforces.com/contest/311/problem/B
namespace cf185div1B {
    ll d[100010], t[100010], T[100010], dp[105][100010];
    void solve() {
        ll n, m, p;
        cin >> n >> m >> p;
        REP(i, n-1) cin >> d[i+1];
        REP(i, n-1) d[i+1] += d[i];
        REP(i, m) {
            ll a, b;
            cin >> a >> b;
            t[i] = (b-d[a-1]);
        }
        sort(t, t+m);
        T[0] = t[0];
        REP(i, m-1) T[i+1] += T[i] + t[i+1];

        REP(i, m) dp[0][i] = (i+1)*t[i] - T[i];
        FOR(i, 1, p) {
            ConvexHullTrick<ll> cht(0, LLINF);
            dp[i][0] = t[0] - T[0];
            cht.insert(0, dp[i-1][0] + T[0]);
            FOR(j, 1, m) {
                dp[i][j] = cht.get(t[j]) + t[j]*j - T[j];
                cht.insert(-j, dp[i-1][j] + T[j]);
            }
        }

        cout << dp[p-1][m-1] << endl;
    }
}

signed main(void)
{
    cin.tie(0);
    ios::sync_with_stdio(false);

    aoj2580::solve();
    // cf185div1B::solve();

    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 11612
final_rank: 6

code_snippet: #include <bits/stdc++.h>

using namespace std;
using ll = long long;
// #define int ll
using PII = pair<ll, ll>;

#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()

template<typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template<typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }
template<typename T> bool IN(T a, T b, T x) { return a<=x&&x<b; }
template<typename T> T ceil(T a, T b) { return a/b + !!(a%b); }

template<typename T> vector<T> make_v(size_t a) { return vector<T>(a); }
template<typename T,typename... Ts>
auto make_v(size_t a,Ts... ts) {
    return vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));
}
template<typename T,typename V> typename enable_if<is_class<T>::value==0>::type
fill_v(T &t, const V &v) { t=v; }
template<typename T,typename V> typename enable_if<is_class<T>::value!=0>::type
fill_v(T &t, const V &v ) { for(auto &e:t) fill_v(e,v); }

template<class S,class T>
ostream &operator <<(ostream& out,const pair<S,T>& a) {
    out<<'('<<a.first<<','<<a.second<<')'; return out;
}
template<class T>
ostream &operator <<(ostream& out,const vector<T>& a){
    out<<'[';
    for(const T &i: a) out<<i<<',';
    out<<']';
    return out;
}
template<class T>
ostream &operator <<(ostream& out, const set<T>& a) {
    out<<'{';
    for(const T &i: a) out<<i<<',';
    out<<'}';
    return out;
}
template<class T, class S>
ostream &operator <<(ostream& out, const map<T,S>& a) {
    out<<'{';
    for(auto &i: a) out<<i<<',';
    out<<'}';
    return out;
}

int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0}; // DRUL
const int INF = 1<<30;
const ll LLINF = 1LL<<60;
const ll MOD = 1000000007;

// 最小を求めてるので最大ならinsert(-a,-b), -get(x)
struct ConvexHullTrick {
    deque<PII> que;

    bool isright(const PII &p1, const PII &p2, int x) {
        return (p1.second-p2.second) >= x * (p2.first-p1.first);
    }
    bool check(const PII &a, const PII &b, const PII &c) {
        return (b.first-a.first)*(c.second-b.second)>=(b.second-a.second)*(c.first-b.first);
    }
    ll f(const PII &p, ll x) { return p.first * x + p.second; }

    // ax + b を追加
    void insert(ll a, ll b) {
        PII p(a, b);
        while(que.size() >= 2 && check(que[que.size()-2], que.back(), p)) {
            que.pop_back();
        }
        que.push_back(p);
    }
    // 単調性がある xの位置での最小のy
    ll incl_query(ll x) {
        assert(que.size());
        while(que.size() >= 2 && f(que[0],x) >= f(que[1],x)) {
            que.pop_front();
        }
        return que[0].first * x + que[0].second;
    }
    // 単調性なし
    ll query(ll x) {
        ll lb = -1, ub = (ll)que.size()-1;
        while(ub-lb > 1) {
            ll mid = (lb+ub)/2;
            if(isright(que[mid], que[mid+1], x)) lb = mid;
            else ub = mid;
        }
        return f(que[ub], x);
    }
};

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2580
namespace aoj2580 {
    ll dp[105][10010];
    void solve() {
        ll n, m, d, x;
        cin >> n >> m >> d >> x;
        vector<ll> p(n), a(m), b(m);
        REP(i, n) cin >> p[i];
        REP(i, m) cin >> a[i] >> b[i];

        REP(i, d) REP(j, n) dp[i][j] = LLINF;

        {
            ll num = 0;
            REP(j, m) {
                ll pos;
                if(b[j] >= 0) {
                    pos = a[j]-b[j];
                } else {
                    pos = a[j]+b[j];
                }
                if(pos >= p[0]) num++;
                a[j] += x;
            }
            REP(i, n) dp[0][i] = num * (p[i] - p[0]);
        }

        FOR(i, 1, d) {
            vector<ll> num(n);
            REP(j, m) {
                ll pos;
                if(b[j] >= 0) {
                    pos = a[j]-b[j];
                } else {
                    pos = a[j]+b[j];
                }
                ll tmp = upper_bound(ALL(p), pos) - p.begin() - 1;
                if(tmp >= 0) num[tmp]++;
                a[j] += x;
            }
            for(ll j=n-2; j>=0; --j) num[j] += num[j+1];

            ConvexHullTrick cht;
            REP(j, n) {
                cht.insert(num[j], dp[i-1][j]-num[j]*p[j]);
                dp[i][j] = cht.query(p[j]);
            }
        }

        ll ret = LLINF;
        REP(i, d) chmin(ret, dp[i][n-1]);
        cout << ret << endl;
    }
}

namespace cf185div1B {
    int d[100010], t[100010], T[100010], dp[105][100010];
    void solve() {
        int n, m, p;
        cin >> n >> m >> p;
        REP(i, n-1) cin >> d[i+1];
        REP(i, n-1) d[i+1] += d[i];
        REP(i, m) {
            int a, b;
            cin >> a >> b;
            t[i] = (b-d[a-1]);
        }
        sort(t, t+m);
        T[0] = t[0];
        REP(i, m-1) T[i+1] += T[i] + t[i+1];

        REP(i, m) dp[0][i] = (i+1)*t[i] - T[i];
        FOR(i, 1, p) {
            ConvexHullTrick cht;
            dp[i][0] = t[0] - T[0];
            cht.insert(0, dp[i-1][0] + T[0]);
            FOR(j, 1, m) {
                dp[i][j] = cht.incl_query(t[j]) + t[j]*j - T[j];
                cht.insert(-j, dp[i-1][j] + T[j]);
            }
        }

        cout << dp[p-1][m-1] << endl;
    }
}

signed main(void)
{
    cin.tie(0);
    ios::sync_with_stdio(false);

    aoj2580::solve();
    // cf185div1B::solve();

    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 11204
final_rank: 4

code_snippet: #include <bits/stdc++.h>

using namespace std;
using ll = long long;
// #define int ll
using PII = pair<ll, ll>;

#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()

template<typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template<typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }
template<typename T> bool IN(T a, T b, T x) { return a<=x&&x<b; }
template<typename T> T ceil(T a, T b) { return a/b + !!(a%b); }

template<typename T> vector<T> make_v(size_t a) { return vector<T>(a); }
template<typename T,typename... Ts>
auto make_v(size_t a,Ts... ts) {
    return vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));
}
template<typename T,typename V> typename enable_if<is_class<T>::value==0>::type
fill_v(T &t, const V &v) { t=v; }
template<typename T,typename V> typename enable_if<is_class<T>::value!=0>::type
fill_v(T &t, const V &v ) { for(auto &e:t) fill_v(e,v); }

template<class S,class T>
ostream &operator <<(ostream& out,const pair<S,T>& a) {
    out<<'('<<a.first<<','<<a.second<<')'; return out;
}
template<class T>
ostream &operator <<(ostream& out,const vector<T>& a){
    out<<'[';
    for(const T &i: a) out<<i<<',';
    out<<']';
    return out;
}
template<class T>
ostream &operator <<(ostream& out, const set<T>& a) {
    out<<'{';
    for(const T &i: a) out<<i<<',';
    out<<'}';
    return out;
}
template<class T, class S>
ostream &operator <<(ostream& out, const map<T,S>& a) {
    out<<'{';
    for(auto &i: a) out<<i<<',';
    out<<'}';
    return out;
}

int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0}; // DRUL
const int INF = 1<<30;
const ll LLINF = 1LL<<60;
const ll MOD = 1000000007;

// // 単調性なしok 動的CHT 各操作O(logN)
// template <typename T, const T id = numeric_limits<T>::min()>
// class ConvexHullTrick {
// private:
//     struct line {
//         T a, b;
//         line(T a_ = 0, T b_ = 0) : a(a_), b(b_) {}
//         T get(T x) { return a * x + b; }
//     };
//     struct node {
//         line l;
//         node *lch, *rch;
//         node(line l_) : l(l_), lch(nullptr), rch(nullptr) {}
//     };
//
//     const T minx, maxx;
//     node *root = nullptr;
//
//     // [lb, ub]
//     node* update(node *p, ll lb, ll ub, line& l) {
//         if (!p) return new node(l);
//         if (p->l.get(lb) >= l.get(lb) && p->l.get(ub) >= l.get(ub)) return p;
//         if (p->l.get(lb) <= l.get(lb) && p->l.get(ub) <= l.get(ub)) {
//           p->l = l;
//           return p;
//         }
//         ll mid = (lb + ub) / 2;
//         if (p->l.get(mid) < l.get(mid)) swap(p->l, l);
//         if (p->l.get(lb) <= l.get(lb)) p->lch = update(p->lch, lb, mid, l);
//         else p->rch = update(p->rch, mid + 1, ub, l);
//         return p;
//     }
//     // [lb, ub]
//     T query(node *p, ll lb, ll ub, ll t) const {
//         if(!p) return id;
//         if(ub == lb) return p->l.get(t);
//         ll mid = (lb+ub)/2;
//         if(t <= mid) return max(p->l.get(t), query(p->lch, lb, mid, t));
//         return max(p->l.get(t), query(p->rch, mid + 1, ub, t));
//     }
// public:
//     // xの範囲
//     ConvexHullTrick(const T minx_, const T maxx_) : minx(minx_), maxx(maxx_) {}
//     // 直線ax+bを追加 最小がほしければ-ax-bを渡してgetの結果に×(-1)する
//     void insert(T a, T b) {
//         line l(a, b);
//         root = update(root, minx, maxx, l);
//     }
//     // ax+b のうち最大のものを返す
//     T get(T x) const { return query(root, minx, maxx, x); }
// };

// 最小を求めてるので最大ならinsert(-a,-b), -get(x)
struct ConvexHullTrick {
    deque<PII> que;

    bool isright(const PII &p1, const PII &p2, int x) {
        return (p1.second-p2.second) >= x * (p2.first-p1.first);
    }
    bool check(const PII &a, const PII &b, const PII &c) {
        return (b.first-a.first)*(c.second-b.second)>=(b.second-a.second)*(c.first-b.first);
    }
    ll f(const PII &p, ll x) { return p.first * x + p.second; }

    // ax + b を追加
    void insert(ll a, ll b) {
        PII p(a, b);
        while(que.size() >= 2 && check(que[que.size()-2], que.back(), p)) {
            que.pop_back();
        }
        que.push_back(p);
    }
    // 単調性がある xの位置での最小のy
    ll incl_query(ll x) {
        assert(que.size());
        while(que.size() >= 2 && f(que[0],x) >= f(que[1],x)) {
            que.pop_front();
        }
        return que[0].first * x + que[0].second;
    }
    // 単調性なし
    ll query(ll x) {
        ll lb = -1, ub = (ll)que.size()-1;
        while(ub-lb > 1) {
            ll mid = (lb+ub)/2;
            // cout << lb << " " << mid << " " << ub << endl;
            if(isright(que[mid], que[mid+1], x)) lb = mid;
            else ub = mid;
        }
        // cout << "ub=" << ub << endl;
        return f(que[ub], x);
    }
};

ll dp[105][10010];
signed main(void)
{
    cin.tie(0);
    ios::sync_with_stdio(false);

    ll n, m, d, x;
    cin >> n >> m >> d >> x;
    vector<ll> p(n), a(m), b(m);
    REP(i, n) cin >> p[i];
    REP(i, m) cin >> a[i] >> b[i];

    REP(i, d) REP(j, n) dp[i][j] = LLINF;

    {
        ll num = 0;
        REP(j, m) {
            ll pos;
            if(b[j] >= 0) {
                pos = a[j]-b[j];
            } else {
                pos = a[j]+b[j];
            }
            if(pos >= p[0]) num++;
            a[j] += x;
        }
        // cout << "num=" << num << endl;
        REP(i, n) dp[0][i] = num * (p[i] - p[0]);
    }

    FOR(i, 1, d) {
        // cout << "i=" << i << endl;
        // num[j] = (i日目に都市jを見ている敵の数)
        vector<ll> num(n);
        REP(j, m) {
            ll pos;
            if(b[j] >= 0) {
                pos = a[j]-b[j];
            } else {
                pos = a[j]+b[j];
            }
            ll tmp = upper_bound(ALL(p), pos) - p.begin() - 1;
            // cout << "j=" << j << " " << pos << " " << tmp << endl;
            if(tmp >= 0) num[tmp]++;
            a[j] += x;
        }
        for(ll j=n-2; j>=0; --j) num[j] += num[j+1];
        // cout << "num=" << num << endl;

        ConvexHullTrick cht;
        REP(j, n) {
            // cout << "j=" << j << endl;
            cht.insert(num[j], dp[i-1][j]-num[j]*p[j]);
            // cout << "a" << endl;
            dp[i][j] = cht.query(p[j]);
        }
    }

    // REP(i, d) {
    //     REP(j, n) cout << dp[i][j] << " ";
    //     cout << endl;
    // }
    ll ret = LLINF;
    REP(i, d) chmin(ret, dp[i][n-1]);
    cout << ret << endl;

    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 11192
final_rank: 3

code_snippet: #include <bits/stdc++.h>

using namespace std;
using ll = long long;
// #define int ll
using PII = pair<ll, ll>;

#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()

template<typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template<typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }
template<typename T> bool IN(T a, T b, T x) { return a<=x&&x<b; }
template<typename T> T ceil(T a, T b) { return a/b + !!(a%b); }

template<typename T> vector<T> make_v(size_t a) { return vector<T>(a); }
template<typename T,typename... Ts>
auto make_v(size_t a,Ts... ts) {
    return vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));
}
template<typename T,typename V> typename enable_if<is_class<T>::value==0>::type
fill_v(T &t, const V &v) { t=v; }
template<typename T,typename V> typename enable_if<is_class<T>::value!=0>::type
fill_v(T &t, const V &v ) { for(auto &e:t) fill_v(e,v); }

template<class S,class T>
ostream &operator <<(ostream& out,const pair<S,T>& a) {
    out<<'('<<a.first<<','<<a.second<<')'; return out;
}
template<class T>
ostream &operator <<(ostream& out,const vector<T>& a){
    out<<'[';
    for(const T &i: a) out<<i<<',';
    out<<']';
    return out;
}
template<class T>
ostream &operator <<(ostream& out, const set<T>& a) {
    out<<'{';
    for(const T &i: a) out<<i<<',';
    out<<'}';
    return out;
}
template<class T, class S>
ostream &operator <<(ostream& out, const map<T,S>& a) {
    out<<'{';
    for(auto &i: a) out<<i<<',';
    out<<'}';
    return out;
}

int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0}; // DRUL
const int INF = 1<<30;
const ll LLINF = 1LL<<60;
const ll MOD = 1000000007;

// // 単調性なしok 動的CHT 各操作O(logN)
// template <typename T, const T id = numeric_limits<T>::min()>
// class ConvexHullTrick {
// private:
//     struct line {
//         T a, b;
//         line(T a_ = 0, T b_ = 0) : a(a_), b(b_) {}
//         T get(T x) { return a * x + b; }
//     };
//     struct node {
//         line l;
//         node *lch, *rch;
//         node(line l_) : l(l_), lch(nullptr), rch(nullptr) {}
//     };
//
//     const T minx, maxx;
//     node *root = nullptr;
//
//     // [lb, ub]
//     node* update(node *p, ll lb, ll ub, line& l) {
//         if (!p) return new node(l);
//         if (p->l.get(lb) >= l.get(lb) && p->l.get(ub) >= l.get(ub)) return p;
//         if (p->l.get(lb) <= l.get(lb) && p->l.get(ub) <= l.get(ub)) {
//           p->l = l;
//           return p;
//         }
//         ll mid = (lb + ub) / 2;
//         if (p->l.get(mid) < l.get(mid)) swap(p->l, l);
//         if (p->l.get(lb) <= l.get(lb)) p->lch = update(p->lch, lb, mid, l);
//         else p->rch = update(p->rch, mid + 1, ub, l);
//         return p;
//     }
//     // [lb, ub]
//     T query(node *p, ll lb, ll ub, ll t) const {
//         if(!p) return id;
//         if(ub == lb) return p->l.get(t);
//         ll mid = (lb+ub)/2;
//         if(t <= mid) return max(p->l.get(t), query(p->lch, lb, mid, t));
//         return max(p->l.get(t), query(p->rch, mid + 1, ub, t));
//     }
// public:
//     // xの範囲
//     ConvexHullTrick(const T minx_, const T maxx_) : minx(minx_), maxx(maxx_) {}
//     // 直線ax+bを追加 最小がほしければ-ax-bを渡してgetの結果に×(-1)する
//     void insert(T a, T b) {
//         line l(a, b);
//         root = update(root, minx, maxx, l);
//     }
//     // ax+b のうち最大のものを返す
//     T get(T x) const { return query(root, minx, maxx, x); }
// };

// 最小を求めてるので最大ならinsert(-a,-b), -get(x)
struct ConvexHullTrick {
    deque<PII> que;

    ConvexHullTrick() {}

    bool isright(const PII &p1, const PII &p2, int x) {
        return (p1.second-p2.second) >= x * (p2.first-p1.first);
    }
    bool check(const PII &a, const PII &b, const PII &c) {
        return (b.first-a.first)*(c.second-b.second)>=(b.second-a.second)*(c.first-b.first);
    }
    int f(const PII &p, int x) { return p.first * x + p.second; }

    // ax + b を追加
    void insert(ll a, ll b) {
        PII p(a, b);
        while(que.size() >= 2 && check(que[que.size()-2], que.back(), p)) {
            que.pop_back();
        }
        que.push_back(p);
    }
    // 単調性がある xの位置での最小のy
    ll incl_query(ll x) {
        assert(que.size());
        while(que.size() >= 2 && f(que[0],x) >= f(que[1],x)) {
            que.pop_front();
        }
        return que[0].first * x + que[0].second;
    }
    // 単調性なし
    ll query(ll x) {
        ll lb = -1, ub = (ll)que.size()-1;
        while(ub-lb > 1) {
            ll mid = (lb+ub)/2;
            // cout << lb << " " << mid << " " << ub << endl;
            if(isright(que[mid], que[mid+1], x)) lb = mid;
            else ub = mid;
        }
        // cout << "ub=" << ub << endl;
        return f(que[ub], x);
    }
};

ll dp[105][10010];
signed main(void)
{
    cin.tie(0);
    ios::sync_with_stdio(false);

    ll n, m, d, x;
    cin >> n >> m >> d >> x;
    vector<ll> p(n), a(m), b(m);
    REP(i, n) cin >> p[i];
    REP(i, m) cin >> a[i] >> b[i];

    REP(i, d) REP(j, n) dp[i][j] = LLINF;

    {
        ll num = 0;
        REP(j, m) {
            ll pos;
            if(b[j] >= 0) {
                pos = a[j]-b[j];
            } else {
                pos = a[j]+b[j];
            }
            if(pos >= p[0]) num++;
            a[j] += x;
        }
        // cout << "num=" << num << endl;
        REP(i, n) dp[0][i] = num * (p[i] - p[0]);
    }

    FOR(i, 1, d) {
        // cout << "i=" << i << endl;
        // num[j] = (i日目に都市jを見ている敵の数)
        vector<ll> num(n);
        REP(j, m) {
            ll pos;
            if(b[j] >= 0) {
                pos = a[j]-b[j];
            } else {
                pos = a[j]+b[j];
            }
            ll tmp = upper_bound(ALL(p), pos) - p.begin() - 1;
            // cout << "j=" << j << " " << pos << " " << tmp << endl;
            if(tmp >= 0) num[tmp]++;
            a[j] += x;
        }
        for(ll j=n-2; j>=0; --j) num[j] += num[j+1];
        // cout << "num=" << num << endl;

        ConvexHullTrick cht;
        REP(j, n) {
            // cout << "j=" << j << endl;
            cht.insert(num[j], dp[i-1][j]-num[j]*p[j]);
            // cout << "a" << endl;
            dp[i][j] = cht.query(p[j]);
        }
    }

    // REP(i, d) {
    //     REP(j, n) cout << dp[i][j] << " ";
    //     cout << endl;
    // }
    ll ret = LLINF;
    REP(i, d) chmin(ret, dp[i][n-1]);
    cout << ret << endl;

    return 0;
}
accuracy: 0.3548387096774194
time_ms: 10
memory_kb: 5688
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;

typedef long long ll;
#define REP(i,n) for(int i=0,_n=(int)(n);i<_n;++i)
#define ALL(v) (v).begin(),(v).end()
#define CLR(t,v) memset(t,(v),sizeof(t))
template<class T1,class T2>ostream& operator<<(ostream& os,const pair<T1,T2>&a){return os<<"("<<a.first<<","<<a.second<< ")";}
template<class T>void pv(T a,T b){for(T i=a;i!=b;++i)cout<<(*i)<<" ";cout<<endl;}
template<class T>void chmin(T&a,const T&b){if(a>b)a=b;}
template<class T>void chmax(T&a,const T&b){if(a<b)a=b;}


const ll INF = (ll)(1e14);

const int MAX_N = 11234;
const int MAX_M = 11234;
const int MAX_D = 112;
ll P[MAX_N];
ll A[MAX_M];

ll w[MAX_D][MAX_N];
ll dp[MAX_D][MAX_N];

struct Line {
  int id;
  ll a, b;
  ll f(ll x) { return a*x + b; }
};

bool check(Line l1, Line l2, Line l3) {
  return (l2.a - l1.a)*(l2.b - l3.b) <= (l3.a - l2.a)*(l1.b - l2.b) ||
    (l1.a == l2.a && l1.b <= l2.b) ||
    (l2.a == l3.a && l2.b >= l3.b);
}

int main2() {
  int N, M;
  ll D, X;
  cin >> N >> M >> D >> X;
  REP(i, N) cin >> P[i+1]; // 1-indexed

  CLR(w, 0);
  REP(_, M) {
    int a, b; cin >> a >> b;
    a -= abs(b);
    for (int i = 1; i <= N; i++) {
      ll D = (P[i]-a+X+X-1)/X;
      if (D < 0) D = 0;
      w[D][i]++;
    }
  }
  for (int i = 1; i <= N; i++) {
    for (int d = 1; d < MAX_D; d++) {
      w[d][i] += w[d-1][i];
    }
  }

  REP(i, MAX_D) REP(j, MAX_N) dp[i][j] = INF;
  dp[1][1] = 0;
  for (int d = 1; d <= D; d++) {
    deque<Line> deq;
    for (int i = 1; i <= N; i++) {

      // ll val = INF;
      // for (int j = 1; j <= i; j++) {
      //   chmin(val, dp[d][j] + (P[i] - P[j]) * w[d][j]);
      //   ll cur = dp[d][j] + (P[i] - P[j]) * w[d][j];
      //   cout << d << " " << j << " ->" << i << " " << cur << endl;
      // }
      // dp[d+1][i] = val;

      Line line = (Line){ i, w[d][i], dp[d][i] - P[i] * w[d][i] };
      while (deq.size() >= 2 && check(deq[deq.size()-2], deq[deq.size()-1], line)) deq.pop_back();
      deq.push_back(line);
      ll x = P[i];
      while (deq.size() >= 2 && deq[0].f(x) >= deq[1].f(x)) deq.pop_front();
      ll val = deq[0].f(x);
      dp[d+1][i] = val;
    }
  }
  ll ans = dp[D+1][N];
  cout << ans << endl;
  return 0;
}

int main() {
  for (;!cin.eof();cin>>ws)
    main2();
  return 0;
}
accuracy: 1
time_ms: 910
memory_kb: 22904
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a,b) (a<(b)?(a=b,1):0)
#define chmin(a,b) (a>(b)?(a=b,1):0)
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
const int INF = 1<<29;
const double EPS = 1e-8;
const double PI = acos(-1);
typedef pair<int,int> pii;
typedef long long ll;
typedef pair<ll, ll> pll;

struct CHT {
  static const ll I = LLONG_MAX;
  CHT() {
    // 番兵
    S.insert({L(I,0), L(-I,0)});
    C.insert(cp(L(I,0),L(-I,0)));
  }
  template<class T>
  void myerase(set<T> &S, T x) {
    assert(S.count(x) == 1);
    S.erase(x);
  }
  // |a|,|b|<I/2  |ab| < LONG_LONG_MAX/2
  void add(ll a, ll b) {
    const L p(a,b);
    It pos = S.insert(p).first;
    if (check(*it_m1(pos), p, *it_p1(pos))) {
      S.erase(pos);
      return;
    }
    // 21307846
    myerase(C,cp(*it_m1(pos), *it_p1(pos)));
    {
      It it = it_m1(pos);
      while(it!=S.begin() && check(*it_m1(it), *it, p)) --it;
      // ++it;
      // if (it != pos)
      //   erase(it, prev(pos));
      erase(it,prev(pos));
      it++;
      S.erase(it,pos);
      pos = S.find(p);
    }
    {
      It it = it_p1(pos);
      while(it_p1(it)!=S.end() && check(p,*it, *it_p1(it))) ++it;
      ++pos;
      // if (pos != it)
      erase(pos, it);
      S.erase(pos, it);
      pos = S.find(p);
    }
    C.insert(cp(*it_m1(pos), *pos));
    C.insert(cp(*pos, *it_p1(pos)));
  }
  ll query(ll x) {
    if ((int)S.size()==2) return 1LL<<55;
    const L &p = (--C.lower_bound(CP(x,1,L(0,0))))->p;
    return p.a*x + p.b;
  }

private:

  template<class T>  inline T it_p1(T a) { return ++a; }
  template<class T>  inline T it_m1(T a) { return --a; }
  struct L {
    ll a, b;
    L(ll a, ll b) : a(a),b(b) {}
    bool operator<(const L &rhs) const {
      return a != rhs.a ? a > rhs.a : b < rhs.b;
    }
  };
  struct CP {
    ll n,d;
    L p;
    CP(ll _n, ll _d, const L &p) : n(_n),d(_d),p(p) {
      if (d < 0) { n *= -1; d *= -1; }
    };
    bool operator<(const CP &rhs) const {
      if (n == I || rhs.n == -I) return 0;
      if (n == -I || rhs.n == I) return 1;
      return n * rhs.d < rhs.n * d;
    }
  };
  set<L> S;
  typedef set<L>::iterator It;
  set<CP> C;

  void erase(It a, It b) {
    for (It it=a; it!=b; ++it)
      myerase(C,cp(*it, *it_p1(it)));
  }
  CP cp(const L &p1, const L &p2) {
    if (p1.a == I) return CP(-I,1,p2);
    if (p2.a == -I) return CP(I,1,p2);
    return CP(p1.b-p2.b, p2.a-p1.a, p2);
  }
  bool check(const L &p1, const L &p2, const L &p3) {
    if (p1.a==p2.a && p1.b <= p2.b) return 1;
    if (p1.a == I || p3.a == -I) return 0;
    return (p2.a-p1.a)*(p3.b-p2.b) >= (p2.b-p1.b)*(p3.a-p2.a);
  }
};

ll p[10000];
ll c[10000];
ll dp[10001][101];

int main() {
  ll n,m,d,x;
  while(cin>>n>>m>>d>>x) {
    REP(i,n) {
      cin >> p[i];
    }
    REP(i,m) {
      int a, b;
      cin >> a >> b;
      if (b > 0) {
        // y = (x-a) + b = 0
        // x = a - b
        c[i] = a-b;
      } else {
        // y = -(x-a) + b = 0
        // x = a + b
        c[i] = a+b;
      }
    }
    sort(c,c+m);
    vector<CHT> cht(d+1);
    vector<ll> id(d+1,0);
    REP(i,n)REP(k,d+1)dp[i][k] = 1LL<<50;
    dp[0][0] = 0;
    while(id[0]<m&&c[id[0]]<p[0]) id[0]++;
    cht[0].add(m-id[0], dp[0][0]-p[0]*(m-id[0]));
    REP(i,n) {
      for (int k=d; k>=1; --k) {
        while(id[k]<m&&c[id[k]]+x*k<p[i]) id[k]++;
        dp[i][k] = cht[k-1].query(p[i]);
        // cout << dp[i][k] << "," << m-id[k] << " " ;
        cht[k].add(m-id[k], dp[i][k]-p[i]*(m-id[k]));

      }
      // cout << endl;
    }
    cout << *min_element(dp[n-1], dp[n-1]+d+1) << endl;
  }
}
accuracy: 1
time_ms: 300
memory_kb: 9616
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a,b) (a<(b)?(a=b,1):0)
#define chmin(a,b) (a>(b)?(a=b,1):0)
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
const int INF = 1<<29;
const double EPS = 1e-8;
const double PI = acos(-1);
typedef pair<int,int> pii;
typedef long long ll;
typedef pair<ll, ll> pll;

struct CHT {
  static const ll I = LLONG_MAX;
  CHT() {
    // 番兵
    S.insert({L(I,0), L(-I,0)});
    C.insert(cp(L(I,0),L(-I,0)));
  }
  // |a|,|b|<I/2  |ab| < LONG_LONG_MAX/2
  void add(ll a, ll b) {
    const L p(a,b);
    It pos = S.insert(p).first;
    if (check(*it_m1(pos), p, *it_p1(pos))) {
      S.erase(pos);
      return;
    }
    C.erase(cp(*it_m1(pos), *it_p1(pos)));
    {
      It it = it_m1(pos);
      while(it!=S.begin() && check(*it_m1(it), *it, p)) --it;
      erase(it, pos);
      S.erase(++it,pos);
      pos = S.find(p);
    }
    {
      It it = it_p1(pos);
      while(it_p1(it)!=S.end() && check(p,*it, *it_p1(it))) ++it;
      erase(++pos, it);
      S.erase(pos, it);
      pos = S.find(p);
    }
    C.insert(cp(*it_m1(pos), *pos));
    C.insert(cp(*pos, *it_p1(pos)));
  }
  ll query(ll x) {
    if ((int)S.size()==2) return 1LL<<55;
    const L &p = (--C.lower_bound(CP(x,1,L(0,0))))->p;
    return p.a*x + p.b;
  }

private:

  template<class T>  inline T it_p1(T a) { return ++a; }
  template<class T>  inline T it_m1(T a) { return --a; }
  struct L {
    ll a, b;
    L(ll a, ll b) : a(a),b(b) {}
    bool operator<(const L &rhs) const {
      return a != rhs.a ? a > rhs.a : b < rhs.b;
    }
  };
  struct CP {
    ll n,d;
    L p;
    CP(ll _n, ll _d, const L &p) : n(_n),d(_d),p(p) {
      if (d < 0) { n *= -1; d *= -1; }
    };
    bool operator<(const CP &rhs) const {
      if (n == I || rhs.n == -I) return 0;
      if (n == -I || rhs.n == I) return 1;
      return n * rhs.d < rhs.n * d;
    }
  };
  set<L> S;
  typedef set<L>::iterator It;
  set<CP> C;

  void erase(It a, It b) {
    for (It it=a; it!=b; ++it)
      C.erase(cp(*it, *it_p1(it)));
  }
  CP cp(const L &p1, const L &p2) {
    if (p1.a == I) return CP(-I,1,p2);
    if (p2.a == -I) return CP(I,1,p2);
    return CP(p1.b-p2.b, p2.a-p1.a, p2);
  }
  bool check(const L &p1, const L &p2, const L &p3) {
    if (p1.a==p2.a && p1.b <= p2.b) return 1;
    if (p1.a == I || p3.a == -I) return 0;
    return (p2.a-p1.a)*(p3.b-p2.b) >= (p2.b-p1.b)*(p3.a-p2.a);
  }
};

ll p[10000];
ll c[10000];
ll dp[10001][101];

int main() {
  ll n,m,d,x;
  while(cin>>n>>m>>d>>x) {
    REP(i,n) {
      cin >> p[i];
    }
    REP(i,m) {
      int a, b;
      cin >> a >> b;
      if (b > 0) {
        // y = (x-a) + b = 0
        // x = a - b
        c[i] = a-b;
      } else {
        // y = -(x-a) + b = 0
        // x = a + b
        c[i] = a+b;
      }
    }
    sort(c,c+m);
    vector<CHT> cht(d+1);
    vector<ll> id(d+1,0);
    REP(i,n)REP(k,d+1)dp[i][k] = 1LL<<50;
    dp[0][0] = 0;
    while(id[0]<m&&c[id[0]]<p[0]) id[0]++;
    cht[0].add(m-id[0], dp[0][0]-p[0]*(m-id[0]));
    REP(i,n) {
      for (int k=d; k>=1; --k) {
        while(id[k]<m&&c[id[k]]+x*k<p[i]) id[k]++;
        dp[i][k] = cht[k-1].query(p[i]);
        // cout << dp[i][k] << "," << m-id[k] << " " ;
        cht[k].add(m-id[k], dp[i][k]-p[i]*(m-id[k]));

      }
      // cout << endl;
    }
    cout << *min_element(dp[n-1], dp[n-1]+d+1) << endl;
  }
}
accuracy: 1
time_ms: 310
memory_kb: 9612
final_rank: 10

code_snippet: // * template

#include <bits/stdc++.h>
#ifdef LOCAL
#include "dump.hpp"
#else
#define dump(...)
#endif

using namespace std;

template<class T> inline void chmax(T &a, const T &b) { if(a < b) a = b; }
template<class T> inline void chmin(T &a, const T &b) { if(a > b) a = b; }

template<class T, class U> inline void fill_array(T &e, const U &v) { e = v; }
template<class T, class U, size_t s> inline void fill_array(T (&a)[s], const U &v) {for(auto&e:a)fill_array(e,v);}
template<class T, class U, size_t s> inline void fill_array(array<T, s> &a, const U &v) {for(auto&e:a)fill_array(e,v);}
template<class T, class U> inline void fill_array(vector<T> &a, const U &v) {for(auto&e:a)fill_array(e,v);}

struct range {
	typedef int Int;
	struct iter {
		Int i;
		const Int s;
		iter(const Int &i_, const Int &s_):i(i_), s(s_) {}
		bool operator!=(const iter &r) const { return s > 0 ? i < r.i : i > r.i; }
		const Int &operator*() const { return i; }
		iter &operator++() { i += s; return *this; }
	};
	const Int f, l, s;
	range(const Int &f_, const Int &l_, const Int &s_):f(f_), l(l_), s(s_) {}
	range(const Int &f_, const Int &l_):f(f_), l(l_), s(1) {}
	range(const Int &num):f(0), l(num), s(1) {}
	iter begin() const { return iter(f, s); }
	iter end() const { return iter(l, s); }
};

// * solve

class BIT {
private:
	int size;
	vector<int> bit;

public:
	BIT(int n = 0):size(n), bit(n + 1, 0) {}

	void add(int i, int x) {
		++i;
		while(i <= size) {
			bit[i] += x;
			i += i & -i;
		}
	}

	int sum(int i) const {
		++i;
		int s = 0;
		while(i > 0) {
			s += bit[i];
			i -= i & -i;
		}
		return s;
	}
};

struct line {
	typedef long long Int;
	Int a, b;
	line(Int a_, Int b_):a(a_), b(b_) {}
	Int operator()(Int x) const {
		return a * x + b;
	}
};

inline bool check(const line &f1, const line &f2, const line &f3) {
	return (f2.a - f1.a) * (f3.b - f2.b) >= (f2.b - f1.b) * (f3.a - f2.a);
}

constexpr int MAX_X = 1e6;

int main() {
	cin.tie(nullptr);
	ios::sync_with_stdio(false);

	int n, m, day, speed;
	cin >> n >> m >> day >> speed;

	vector<int> pos(n);
	for(auto &e : pos) cin >> e;

	BIT bit(MAX_X + 2);
	bit.add(0, m);

	vector<int> enemy(m);
	for(auto &e : enemy) {
		int a, b;
		cin >> a >> b;
		e = a - abs(b);
		bit.add(max(e + 1, 0), -1);
	}


	vector<long long> dp(n, 1e12);
	dp[0] = 0;

	const auto make_f = [&](int i) { const long long w = bit.sum(pos[i]); return line(w, dp[i] - w * pos[i]); };

	for(const int d : range(day)) {
		vector<long long> next_dp(dp);
		deque<line> deq{make_f(0)};
		for(const int i : range(1, n)) {
			const int &p = pos[i];

			while(deq.size() > 1 && deq[0](p) >= deq[1](p)) deq.pop_front();

			chmin(next_dp[i], deq.front()(p));

			const auto f = make_f(i);
			while(deq.size() > 1 && check(deq[deq.size() - 2], deq.back(), f)) deq.pop_back();
			deq.emplace_back(move(f));
		}

		dp = move(next_dp);
		dump(dp);
		for(auto &e : enemy) {
			bit.add(max(e + 1, 0), 1);
			e = min(e + speed, MAX_X + 1);
			bit.add(max(e + 1, 0), -1);
		}
	}

	cout << dp.back() << endl;

	return EXIT_SUCCESS;
}
accuracy: 1
time_ms: 40
memory_kb: 5332
final_rank: 2

code_snippet: // * template

#include <bits/stdc++.h>
#ifdef LOCAL
#include "dump.hpp"
#else
#define dump(...)
#endif

using namespace std;

template<class T> inline void chmax(T &a, const T &b) { if(a < b) a = b; }
template<class T> inline void chmin(T &a, const T &b) { if(a > b) a = b; }

template<class T, class U> inline void fill_array(T &e, const U &v) { e = v; }
template<class T, class U, size_t s> inline void fill_array(T (&a)[s], const U &v) {for(auto&e:a)fill_array(e,v);}
template<class T, class U, size_t s> inline void fill_array(array<T, s> &a, const U &v) {for(auto&e:a)fill_array(e,v);}
template<class T, class U> inline void fill_array(vector<T> &a, const U &v) {for(auto&e:a)fill_array(e,v);}

struct range {
	typedef int Int;
	struct iter {
		Int i;
		const Int s;
		iter(const Int &i_, const Int &s_):i(i_), s(s_) {}
		bool operator!=(const iter &r) const { return s > 0 ? i < r.i : i > r.i; }
		const Int &operator*() const { return i; }
		iter &operator++() { i += s; return *this; }
	};
	const Int f, l, s;
	range(const Int &f_, const Int &l_, const Int &s_):f(f_), l(l_), s(s_) {}
	range(const Int &f_, const Int &l_):f(f_), l(l_), s(1) {}
	range(const Int &num):f(0), l(num), s(1) {}
	iter begin() const { return iter(f, s); }
	iter end() const { return iter(l, s); }
};

// * solve

class BIT {
private:
	int size;
	vector<int> bit;

public:
	BIT(int n = 0):size(n), bit(n + 1, 0) {}

	void add(int i, int x) {
		++i;
		while(i <= size) {
			bit[i] += x;
			i += i & -i;
		}
	}

	int sum(int i) const {
		++i;
		int s = 0;
		while(i > 0) {
			s += bit[i];
			i -= i & -i;
		}
		return s;
	}
};

struct line {
	typedef long long Int;
	Int a, b;
	line(Int a_, Int b_):a(a_), b(b_) {}
	Int operator()(Int x) const {
		return a * x + b;
	}
};

inline bool check(const line &f1, const line &f2, const line &f3) {
	return (f2.a - f1.a) * (f3.b - f2.b) >= (f2.b - f1.b) * (f3.a - f2.a);
}

constexpr int MAX_X = 1e6;

int main() {
	cin.tie(nullptr);
	ios::sync_with_stdio(false);

	int n, m, day, speed;
	cin >> n >> m >> day >> speed;

	vector<int> pos(n);
	for(auto &e : pos) cin >> e;

	BIT bit(MAX_X + 2);
	bit.add(0, m);

	vector<int> enemy(m);
	for(auto &e : enemy) {
		int a, b;
		cin >> a >> b;
		e = a - abs(b);
		bit.add(max(e + 1, 0), -1);
	}


	vector<long long> dp(n, 1e12);
	dp[0] = 0;

	const auto make_f = [&](int i) { const int w = bit.sum(pos[i]); return line(w, dp[i] - w * pos[i]); };

	for(const int d : range(day)) {
		vector<long long> next_dp(dp);
		deque<line> deq{make_f(0)};
		for(const int i : range(1, n)) {
			const int &p = pos[i];

			while(deq.size() > 1 && deq[0](p) >= deq[1](p)) deq.pop_front();

			chmin(next_dp[i], deq.front()(p));

			const auto f = make_f(i);
			while(deq.size() > 1 && check(deq[deq.size() - 2], deq.back(), f)) deq.pop_back();
			deq.emplace_back(move(f));
		}

		dp = move(next_dp);
		dump(dp);
		for(auto &e : enemy) {
			bit.add(max(e + 1, 0), 1);
			e = min(e + speed, MAX_X + 1);
			bit.add(max(e + 1, 0), -1);
		}
	}

	cout << dp.back() << endl;

	return EXIT_SUCCESS;
}
accuracy: 0.3548387096774194
time_ms: 20
memory_kb: 5244
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a,b) (a<(b)?(a=b,1):0)
#define chmin(a,b) (a>(b)?(a=b,1):0)
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
const int INF = 1<<29;
const double EPS = 1e-8;
const double PI = acos(-1);
typedef pair<int,int> pii;
typedef long long ll;
typedef pair<ll, ll> pll;

struct CHT {
  vector<pll> deq;              // first * x + second
  ll s,t;
  CHT(ll n) {
    deq.resize(n);
    s=0, t=0;
  }
  void add(ll a, ll b) {      // a : non increasing
    const pll p(a,b);
    while(s+1<t && check(deq[t-2],deq[t-1],p)) t--;
    deq[t++] = p;
  }
  ll incl_query(ll x) {            // x : non decreasing
    if (s==t) {
      return 1LL<<55;
    }
    while(s+1<t && f(deq[s], x) >= f(deq[s+1], x)) s++;
    return f(deq[s], x);
  }
  ll query(ll x) {           // without condition
    ll low = s-1, high = t-1;
    while(low+1<high) {
      ll mid = low+high>>1;
      if (isright(deq[mid], deq[mid+1], x)) low = mid;
      else high = mid;
    }
    return f(deq[high], x);
  }
private:
  bool isright(const pll &p1, const pll &p2, ll x) {
    return (p1.second-p2.second) >= x * (p2.first-p1.first);
  }
  bool check(const pll &p1, const pll &p2, const pll &p3) {
    return (p2.first-p1.first)*(p3.second-p2.second) >=
      (p2.second-p1.second)*(p3.first-p2.first);
  }
  ll f(const pll &p, ll x) {
    return p.first * x + p.second;
  }
};

ll p[10000];
ll c[10000];
ll dp[10001][101];

int main() {
  ll n,m,d,x;
  while(cin>>n>>m>>d>>x) {
    REP(i,n) {
      cin >> p[i];
    }
    REP(i,m) {
      int a, b;
      cin >> a >> b;
      if (b > 0) {
        // y = (x-a) + b = 0
        // x = a - b
        c[i] = a-b;
      } else {
        // y = -(x-a) + b = 0
        // x = a + b
        c[i] = a+b;
      }
    }
    sort(c,c+m);
    vector<CHT> cht(d+1, n);
    vector<ll> id(d+1,0);
    REP(i,n)REP(k,d+1)dp[i][k] = 1LL<<50;
    dp[0][0] = 0;
    while(id[0]<m&&c[id[0]]<p[0]) id[0]++;
    cht[0].add(m-id[0], dp[0][0]-p[0]*(m-id[0]));
    REP(i,n) {
      for (int k=d; k>=1; --k) {
        while(id[k]<m&&c[id[k]]+x*k<p[i]) id[k]++;
        dp[i][k] = cht[k-1].incl_query(p[i]);
        // cout << dp[i][k] << "," << m-id[k] << " " ;
        cht[k].add(m-id[k], dp[i][k]-p[i]*(m-id[k]));

      }
      // cout << endl;
    }
    cout << *min_element(dp[n-1], dp[n-1]+d+1) << endl;
  }
}
accuracy: 1
time_ms: 30
memory_kb: 25268
final_rank: 15