QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#386166#7605. Yet Another Mex Problembear0131RE 0ms0kbC++146.1kb2024-04-11 13:21:082024-04-11 13:21:10

Judging History

你现在查看的是最新测评结果

  • [2024-04-11 13:21:10]
  • 评测
  • 测评结果:RE
  • 用时:0ms
  • 内存:0kb
  • [2024-04-11 13:21:08]
  • 提交

answer

#include<bits/stdc++.h>
#define rep(i, n) for(int i = 0; i < (n); ++i)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
typedef array<int, 3> ai3;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fll;
const int Mod = 1e9 + 7;
inline int sign(int a){ return (a&1) ? (Mod-1) : 1; }
inline void uadd(int &a, int b){ a += b-Mod; a += (a>>31) & Mod; }
inline void usub(int &a, int b){ a -= b, a += (a>>31) & Mod; }
inline void umul(int &a, int b){ a = (int)(1ll * a * b % Mod); }
inline int add(int a, int b){ a += b-Mod; a += (a>>31) & Mod; return a; }
inline int sub(int a, int b){ a -= b, a += (a>>31) & Mod; return a; }
inline int mul(int a, int b){ a = (int)(1ll * a * b % Mod); return a; }
int qpow(int b, ll p){ int ret = 1; while(p){ if(p&1) umul(ret, b); umul(b, b), p >>= 1; } return ret; }
const int fN = 100;
int fact[fN], invfact[fN], inv[fN];
void initfact(int n){
	fact[0] = 1; for(int i = 1; i <= n; ++i) fact[i] = mul(fact[i-1], i);
	invfact[n] = qpow(fact[n], Mod-2); for(int i = n; i > 0; --i) invfact[i-1] = mul(invfact[i], i);
	for(int i = 1; i <= n; ++i) inv[i] = mul(invfact[i], fact[i-1]);
}
int binom(int n, int m){ return (m < 0 || m > n) ? 0 : mul(fact[n], mul(invfact[m], invfact[n-m])); }
const double pi = acos(-1);
inline void chmax(int &a, int b){ (b>a) ? (a=b) : 0; }
inline void chmin(int &a, int b){ (b<a) ? (a=b) : 0; }
inline void chmax(ll &a, ll b){ (b>a) ? (a=b) : 0; }
inline void chmin(ll &a, ll b){ (b<a) ? (a=b) : 0; }

int n;

struct line{
	ll k, b;
	line(){ k = 0, b = -INF; }
	line(ll _k, ll _b){ k = _k, b = _b; }
	inline ll gety(ll x){ return k * x + b; }
};

namespace ktt{
	// max(f[j] + pre[j] * (-x))
	line dat[200200];
	const int B = 450;
	int nxt[200200], out[200200];
	void rebuild(int bi){
		int bl = bi * B, br = min(n, (bi+1) * B);
		for(int i = br-1; i >= bl; --i){
			if(nxt[i] >= br) out[i] = i;
			else out[i] = out[nxt[i]];
		}
	}

	int h[200200], sp = 0;
	bool elim(int a, int b, int c){
		return (__int128)(dat[b].k - dat[a].k) * (dat[c].b - dat[a].b) - (__int128)(dat[c].k - dat[a].k) * (dat[b].b - dat[a].b) >= 0;
	}
	void ins(int i, line l){
		//cerr << "! ins " << i << "   " << l.k << "x + " << l.b << endl;
		nxt[i] = inf, dat[i] = l;
		rebuild(i / B);
		while((sp && dat[h[sp-1]].k == l.k) || (sp >= 2 && elim(h[sp-2], h[sp-1], i))) 
			nxt[h[--sp]] = i, rebuild(h[sp] / B);
		h[sp++] = i;
		//rep(j, sp) cerr << h[j] << " ";
		//cerr << endl;
	}
	ll qry(int tl, int x){
		//cerr << "! qry " << tl << " " << x << " = ";
		ll ret = -INF;
		//for(int i = tl; i < n; ++i) chmax(ret, dat[i].gety(x));
		//cerr << ret << endl;
		//return ret;
		{
			int lb = 0, ub = sp-2;
			while(lb <= ub){
				int mid = (lb+ub) >> 1;
				if(h[mid] < tl || dat[h[mid+1]].gety(x) > dat[h[mid]].gety(x))
					lb = mid+1;
				else 
					ub = mid-1;
			}
			if(h[lb] >= tl) ret = dat[h[lb]].gety(x);
		}
		{
			auto isup = [&](int p){
				return nxt[p] != inf && dat[nxt[p]].gety(x) > dat[p].gety(x);
			};
			int p = tl;
			while(isup(out[p])) p = nxt[out[p]];
			while(isup(p)) p = nxt[p];
			chmax(ret, dat[p].gety(x));
		}
		//cerr << ret << endl;
		return ret;
	}
}

ll pre[200200];

namespace lct{
	// max(k * pre[j] + b)
	line dat[525252];
	void ins(int tl, int tr, line cur, int l, int r, int k){
		//cout << "ins " << tl << " " << tr << " " << l << " " << r << " " << k << endl;
		if(tl > r || l > tr) return ;
		int mid = (l+r) >> 1;
		if(tl <= l && r <= tr){
			if(dat[k].gety(pre[mid]) < cur.gety(pre[mid])) swap(cur, dat[k]);
			if(l == r) return ;
			if(dat[k].gety(pre[l]) < cur.gety(pre[l])) ins(tl, tr, cur, l, mid, k+k);
			if(dat[k].gety(pre[r]) < cur.gety(pre[r])) ins(tl, tr, cur, mid+1, r, k+k+1);
		} else 
			ins(tl, tr, cur, l, mid, k+k), ins(tl, tr, cur, mid+1, r, k+k+1);
	}
	ll qry(int p, int l, int r, int k){
		ll ret = dat[k].gety(pre[p]);
		if(l < r){
			int mid = (l+r) >> 1;
			chmax(ret, (p <= mid) ? qry(p, l, mid, k+k) : qry(p, mid+1, r, k+k+1));
		}
		return ret;
	}
}

int k, a[200200];
vi ps[200200];
multiset< array<int, 3> > st; // mex, left bound, start time
ll f[200200];

void ins(int fl, int fr, int tl, int tr, int v){
	//cout << "------ins " << fl << " " << fr << " " << tl << " " << tr << " " << v << "--------" << endl;
	for(int i = max(fl, tl - k); i <= min(fr, tr - k); ++i){
		lct::ins(tl, i + k, line(v, f[i] - v * pre[i]), 0, n, 1);
	}
	if(tr - k < fr){
		ll b = ktt::qry(max(fl, tr - k + 1), -v);
		lct::ins(tl, tr, line(v, b), 0, n, 1);
	}
}

int main(){
	freopen("b.in", "r", stdin);
	freopen("b.out", "w", stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin >> n >> k;
	rep(i, n) cin >> a[i], ps[a[i]].push_back(i);
	rep(i, n) pre[i+1] = pre[i] + a[i];

	{
		static int cnt[200200];
		int cur = 0;
		rep(i, n){
			++cnt[a[i]];
			if(cnt[cur]){
				while(cnt[cur]) ++cur;
				st.insert({cur, i, 0});
			}
		}
		st.insert({inf, n, 0});
	}

	memset(ktt::nxt, 0x3f, sizeof(ktt::nxt));

	f[0] = 0, ktt::ins(0, line(pre[0], f[0]));
	rep(i, n + 1){
		//cout << "----------------" << i << "-------------------" << endl;
		//for(auto p : st) cout << "{" << p[0] << ", " << p[1] << ", " << p[2] << "} ";
		//cout << endl;
		if(i) f[i] = max(f[i-1], lct::qry(i, 0, n, 1)), ktt::ins(i, line(pre[i], f[i]));
		//cout << "f[" << i << "] = " << f[i] << "\n";
		if(i < n){
			auto it = st.lower_bound({a[i], 0, 0});
			int nxt = (int)(lower_bound(ps[a[i]].begin(), ps[a[i]].end(), i+1) - ps[a[i]].begin());
			//cout << "[" << nxt << "] = ";
			nxt = (nxt == (int)ps[a[i]].size() ? n : ps[a[i]][nxt]);
			//cout << nxt << endl;
			int tmpl = (*it)[1];
			if(tmpl < nxt){
				int ok = 1;
				while(ok){
					int r = (*next(it))[1];
					ins((*it)[2], i, (*it)[1] + 1, r, (*it)[0]);
					if(nxt <= r) ok = 0;
					if(nxt < r) st.insert({(*it)[0], nxt, (*it)[2]});
					it = st.erase(it);
				}
				if(a[i]) st.insert({a[i], tmpl, i});
			}
		}
	}

	cout << f[n] << "\n";

	return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 0
Dangerous Syscalls

input:

5 3
3 4 0 0 3

output:


result: