Submission #589745

#TimeUsernameProblemLanguageResultExecution timeMemory
5897458e7Fish 2 (JOI22_fish2)C++17
100 / 100
1903 ms291412 KiB
//Challenge: Accepted
#include <bits/stdc++.h>
using namespace std;
#ifdef zisk
void debug(){cout << endl;}
template<class T, class ... U> void debug(T a, U ... b){cout << a << " ", debug(b...);}
template<class T> void pary(T l, T r) {
	while (l != r) cout << *l << " ", l++;
	cout << endl;
}
#else
#define debug(...) 0
#define pary(...) 0
#endif
#define ll long long
#define maxn 100005
#define pii pair<int, int>
#define ff first
#define ss second
#define io ios_base::sync_with_stdio(0);cin.tie(0);
const int inf = 1<<30;

struct segtree_interval{
	stack<pii> stk[4*maxn];	
	bool in (pii &p, int x) {
		return p.ff <= x && x <= p.ss;
	}
	void remove(int cur, int l, int r, int ind, vector<pii> &v) {
		if (r <= l) return;
		while (stk[cur].size() && in(stk[cur].top(), ind)) {
			v.push_back(stk[cur].top());
			stk[cur].pop();
		}
		int m = (l + r) / 2;
		if (ind < m) remove(cur*2, l, m, ind, v);
		else if (ind > m) remove(cur*2+1, m+1, r, ind, v);
	}
	void ins(int cur, int l, int r, pii p) {
		if (r <= l) return;
		int m = (l + r) / 2;
		if (in(p, m)) {
			stk[cur].push(p);
			return;
		}
		if (m > p.ss) ins(cur*2, l, m, p);
		else if (m < p.ff) ins(cur*2+1, m+1, r, p);
	}
} inter;
struct segtree_mincnt{
	pii seg[4*maxn];
	int tag[4*maxn];
	void init(int cur, int l, int r) {
		if (r <= l) return;
		seg[cur].ss = (r - l);
		if (r - l == 1) return;
		int m = (l + r) / 2;
		init(cur*2, l, m), init(cur*2+1, m, r);
	}
	void push(int cur, int l, int r) {
		seg[cur].ff += tag[cur];
		if (r - l > 1) {
			tag[cur*2] += tag[cur];
			tag[cur*2+1] += tag[cur];
		}
		tag[cur] = 0;
	}
	void merge(pii &a, pii &b, pii &c) {
		a.ff = min(b.ff, c.ff);
		a.ss = (b.ff == a.ff ? b.ss : 0) + (c.ff == a.ff ? c.ss : 0);
	}
	void pull(int cur, int l, int r) {
		int m = (l + r) / 2;
		push(cur*2, l, m), push(cur*2+1, m, r);
		merge(seg[cur], seg[cur*2], seg[cur*2+1]);
	}
	void modify(int cur, int l, int r, int ql, int qr, int v) {
		if (r <= l || ql >= r || qr <= l) return;
		push(cur, l, r);
		if (ql <= l && qr >= r) {
			tag[cur] += v;
			return;
		}
		int m = (l + r) / 2;
		modify(cur*2, l, m, ql, qr, v); 
		modify(cur*2+1, m, r, ql, qr, v); 
		pull(cur, l, r);
	}
	pii query(int cur, int l, int r, int ql, int qr) {
		if (r <= l || ql >= r || qr <= l) return {inf, 0};
		push(cur, l, r);
		if (ql <= l && qr >= r) return seg[cur];
		int m = (l + r) / 2;
		pii ret, vl = query(cur*2, l, m, ql, qr), vr = query(cur*2+1, m, r, ql, qr);
		merge(ret, vl, vr);
		return ret;
	}
} mincnt;

struct segtree{
	ll seg[4*maxn], tag[4*maxn];
	void init(int cur, int l, int r, ll a[]) {
		if (r <= l) return;
		if (r - l == 1) {
			seg[cur] = a[l];
			return;
		}
		int m = (l + r) / 2;
		init(cur*2, l, m, a), init(cur*2+1, m, r, a);
		seg[cur] = max(seg[cur*2], seg[cur*2+1]);
	}
	void push(int cur, int l, int r) {
		seg[cur] += tag[cur];
		if (r - l > 1) {
			tag[cur*2] += tag[cur];
			tag[cur*2+1] += tag[cur];
		}
		tag[cur] = 0;
	}
	void pull(int cur, int l, int r) {
		int m = (l + r) / 2;
		push(cur*2, l, m), push(cur*2+1, m, r);
		seg[cur] = max(seg[cur*2], seg[cur*2+1]);
	}
	void modify(int cur, int l, int r, int ql, int qr, ll x) {
		if (r <= l || ql >= r || qr <= l) return;
		push(cur, l, r);
		if (ql <= l && qr >= r) {
			tag[cur] += x;
			return;
		}
		int m = (l + r) / 2;
		modify(cur*2, l, m, ql, qr, x);
		modify(cur*2+1, m, r, ql, qr, x);
		pull(cur, l, r);
	}
	int search(int cur, int l, int r, int ql, int qr, bool type, ll t) {
		//type 0: left, 1:right
		push(cur, l, r);
		if (r <= l || ql >= r || qr <= l || seg[cur] < t) return -1;
		if (r - l == 1) return l;
		int m = (l + r) / 2;
		if (type) {
			int vr = search(cur*2+1, m, r, ql, qr, type, t);
			if (vr != -1) return vr;
			return search(cur*2, l, m, ql, qr, type, t);
		} else {
			int vl = search(cur*2, l, m, ql, qr, type, t);
			if (vl != -1) return vl;
			return search(cur*2+1, m, r, ql, qr, type, t);
		}
	}
	ll query(int cur, int l, int r, int x) { //getpnt
		if (r <= l) return 0;
		push(cur, l, r);
		if (r - l == 1) return seg[cur];
		int m = (l + r) / 2;
		if (x < m) return query(cur*2, l, m, x);
		else query(cur*2+1, m, r, x);
	}
	void print(int cur, int l, int r) {
		if (r <= l) return;
		push(cur, l, r);
		if (r - l == 1) {
			debug(seg[cur]);
			return;
		}
		int m = (l + r) / 2;
		print(cur*2, l, m);
		print(cur*2+1, m, r);
	}
} tr, lb, rb; 
struct BIT{
	ll bit[maxn];
	void modify(int ind, ll val) {
		ind++;
		for (;ind < maxn;ind += ind & (-ind)) bit[ind] += val;
	}
	ll query(int ind) {
		ll ret = 0;
		ind++;
		for (;ind > 0;ind -= ind & (-ind)) ret += bit[ind];
		return ret;
	}
	ll sum(int l, int r) {
		return query(r) - query(l-1);	
	}
} sum;
ll a[maxn];
int main() {
	io
	int n, q;
	cin >> n;
	for (int i = 0;i < n;i++) {
		cin >> a[i];
		sum.modify(i, a[i]);
	}
	bool ini = 1;
	auto check = [&] (int l, int r, ll s) { //stuck in [l, r]
		if (r < l) return;
		if (ini) s = sum.sum(l, r);
	
		if(!((l && s >= a[l-1]) || (r < n - 1 && s >= a[r+1]))) {
			//debug(l, r);
			inter.ins(1, 0, n, {l, r});				
			mincnt.modify(1, 0, n, l, r+1, 1);	
		}
	};
	tr.init(1, 0, n, a);
	mincnt.init(1, 0, n);
	{
		ll pref[maxn];
		for (int i = 0;i < n;i++) {
			pref[i] = a[i] + (i ? pref[i-1] : 0);
			lb.modify(1, 0, n, i, i+1, a[i] - (i ? pref[i-1] : 0));	
			rb.modify(1, 0, n, i, i+1, a[i] + pref[i]);
		}
		
		stack<int> stk;
		for (int i = 0;i < n;i++) {
			while (stk.size() && a[i] >= a[stk.top()]) {
				check(stk.top()+1, i-1, 0);
				stk.pop();	
			}
			if (stk.size()) check(stk.top()+1, i-1, 0);	
			else check(0, i-1, 0);
			stk.push(i);
		}
		while (stk.size()) {
			check(stk.top()+1, n-1, 0);
			stk.pop();
		}
	}
	ini = 0;
	cin >> q;
	while (q--) {
		int type;
		cin >> type;
		if (type == 1) {
			int i, y;
			cin >> i >> y;
			i--;
			ll d = y - a[i];
			tr.modify(1, 0, n, i, i+1, d); 
			lb.modify(1, 0, n, i, i+1, d);
			rb.modify(1, 0, n, i, i+1, d);
			lb.modify(1, 0, n, i+1, n, -d);
			rb.modify(1, 0, n, i, n, d);
			sum.modify(i, d);
			a[i] = y;

			vector<pii> rem;
			inter.remove(1, 0, n, i, rem);
			inter.remove(1, 0, n, i-1, rem);
			inter.remove(1, 0, n, i+1, rem);
			for (auto p:rem) {
				//debug("rem", p.ff, p.ss);
				mincnt.modify(1, 0, n, p.ff, p.ss+1, -1);
			}
			vector<int> lef, rig;
			int cur = i+1;		
			ll s = a[i];
			if (i+1 < n) {
				if (a[i+1] < s) s = a[i+1], cur = i+2;
				lef.push_back(i+1);
			}
			while (cur < n) {
				int nxt = tr.search(1, 0, n, cur, n, 0, s+1);
				if (nxt != -1) {
					rig.push_back(nxt-1);
					cur = nxt;
					s += a[nxt];
				} else {
					break;
				}
			}
			rig.push_back(n-1);	
			cur = i-1, s = a[i];	
			if (i-1 >= 0) {
				if (a[i-1] < s) s = a[i-1], cur = i-2;
				rig.insert(rig.begin(), i-1);
			}
			while (cur >= 0) {
				int nxt = tr.search(1, 0, n, 0, cur+1, 1, s+1);
				if (nxt != -1) {
					lef.push_back(nxt+1);
					cur = nxt;
					s += a[nxt];
				} else {
					break;
				}
			}
			lef.push_back(0);

			lef.resize(int(unique(lef.begin(), lef.end()) - lef.begin()));
			rig.resize(int(unique(rig.begin(), rig.end()) - rig.begin()));
			vector<ll> ls, rs;
			for (int I:lef) ls.push_back(sum.query(I-1)); 
			for (int I:rig) rs.push_back(sum.query(I));
			for (int I = 0;I < lef.size();I++) {
				for (int j = 0;j < rig.size();j++) {
					check(lef[I], rig[j], rs[j] - ls[I]);
				}
			}

		} else {
			int l, r;
			cin >> l >> r;
			l--; //[l, r)
			ll suml = -sum.query(l-1)+1, sumr = sum.query(r-1)+1;
			int il = lb.search(1, 0, n, l, r, 1, suml);
			int ir = rb.search(1, 0, n, l, r, 0, sumr)+1;
			if (il != -1) l = il;
			if (ir != -1) r = ir;
			cout << mincnt.query(1, 0, n, l, r).ss << "\n";
		}
	}
}
/*
*/

Compilation message (stderr)

fish2.cpp: In member function 'void segtree::print(int, int, int)':
fish2.cpp:12:20: warning: statement has no effect [-Wunused-value]
   12 | #define debug(...) 0
      |                    ^
fish2.cpp:164:4: note: in expansion of macro 'debug'
  164 |    debug(seg[cur]);
      |    ^~~~~
fish2.cpp: In function 'int main()':
fish2.cpp:299:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  299 |    for (int I = 0;I < lef.size();I++) {
      |                   ~~^~~~~~~~~~~~
fish2.cpp:300:22: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  300 |     for (int j = 0;j < rig.size();j++) {
      |                    ~~^~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...