Code Festival Team Relay F - Capture
問題ページ
F - Capture
考えたこと
- 尺取りとかするのかと思ったがどこまでで区間を伸ばすのを止めるのかわからない
- iまで網をかけている状況で[i,i+1]に新たに網をかけたときの利益の増加はv[i] = s[i+1] + (x[i+1] - x[i])になる
- 数列vの累積和を取れば区間[l,r]に新たに網をかけたときの利益の増加がO(1)で求められる
- 区間の左端lを固定すると最大になる利益はs[l] + max([l,n-1]) - v[l] となる
- 区間maxはセグ木などでO(logN)で求められるのでO(NlogN)で求められる
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define int ll typedef vector<int> VI; typedef vector<VI> VVI; typedef pair<int, int> PII; #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() #define IN(a, b, x) (a<=x&&x<b) #define PB push_back const ll LLINF = (1LL<<60); const int INF = (1LL<<30); const int MOD = 1000000007; 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> T ceil(T a, T b) { return a/b + !!(a%b); } 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<<'['; REP(i, a.size()) {out<<a[i];if(i!=a.size()-1)out<<',';} out<<']'; return out; } int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0}; int x[200010], s[200010], dp[200010]; template<class T> class segmentTree { public: int size_; vector<T> dat; T init__ = -LLONG_MAX; // 単位元 segmentTree() {} segmentTree(int n) { for(size_ = 1; size_ < n; size_ *= 2); dat.assign(2*size_-1, init__); } T calc(T d1, T d2) { // return min(d1, d2); // minnimum return max(d1, d2); // maximum // return d1+d2; // sum } T query(int a, int b, int k, int l, int r) { if(r <= a || b <= l) return init__; if(a <= l && r <= b) return dat[k]; return calc(query(a, b, 2*k+1, l, (l+r)/2), query(a, b, 2*k+2, (l+r)/2, r)); } // [a, b) T query(int a, int b) {return query(a, b, 0, 0, size_);} void update(int k, T a) { k += size_ - 1; dat[k] = a; // max or min // dat[k] += a; // sum while(k > 0) { k = (k-1) / 2; dat[k] = calc(dat[k*2+1], dat[k*2+2]); } } }; signed main(void) { int n; cin >> n; segmentTree<int> seg(n); REP(i, n) cin >> x[i] >> s[i]; FOR(i, 1, n) { dp[i] = s[i] - (x[i]-x[i-1]); dp[i] += dp[i-1]; } REP(i, n) { seg.update(i, dp[i]); } int ret = 0; REP(i, n) { chmax(ret, s[i] + seg.query(i, n) - dp[i]); } cout << ret << endl; return 0; }