90pts求调
查看原帖
90pts求调
589961
steambird楼主2024/11/23 17:49

线段树优化 dp

无解的情况判成有解,不知道为啥

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

constexpr int L = 1e6+5, LS = 4e6+5, INF = 1e8;

//#define int long long

int symb[L], vs[L], vn = 0, n, l, ra, rb;
int lrange[LS], rrange[LS], val[LS];

inline int maxi(int a, int b) {
	return a > b ? a : b;
}

inline int mini(int a, int b) {
	return a < b ? a : b;
}

#define lch (root<<1)
#define rch ((root<<1)|1)
#define mids() int mid = (lrange[root] + rrange[root]) >> 1
#define lcall lch, maxi(lrange[root], l), mini(mid, rrange[root])
#define rcall rch, maxi(mid+1, l), mini(rrange[root], r)

void build(int root, int l, int r) {
	if (l > r) return;
	lrange[root] = l; rrange[root] = r;
	val[root] = INF;	// i.e., not available...
	if (l == r) return;
	mids();
	build(lch, l, mid);
	build(rch, mid+1, r);
}

int query(int root, int l, int r) {
	if (l > r) return INF;
	if (lrange[root] >= l && rrange[root] <= r) return val[root];
	mids();
	return mini(query(lcall), query(rcall));
}

// Single point update only
void update(int root, int pos, int value) {
	if (lrange[root] == pos && rrange[root] == pos) {
		val[root] = value;
		return;
	}
	mids();
	if (pos <= mid) {
		update(lch, pos, value);
	} else {
		update(rch, pos, value);
	}
	// Necessary to pushup
	val[root] = mini(val[lch], val[rch]);
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	
	cin>>n>>l>>ra>>rb;
	for (int i = 1; i <= n; i++) {
		int s,e;
		cin>>s>>e;
		symb[s+1]++;
		symb[e]--;	// Allowed directly there
	}
	ra<<=1; rb<<=1;
	vs[++vn] = 0;
	for (int i = 1; i <= l; i++) {			// Consider that the latter point manages sequence
		if (i > 0) symb[i] += symb[i-1];	// i.e. point i --> (i-1, i] sequence
		if ((i % 2 == 0) && symb[i] == 0) vs[++vn] = i;
	}
//	cerr << "valid positions are:\n";
//	for (int i = 1; i <= vn; i++) cerr<<vs[i]<<' ';
//	cerr<<endl;
//	assert(vs[vn] == l);
	build(1, 1, vn);
	update(1, 1, 0);
//	cerr << "end of build\n";
	for (int i = 2; i <= vn; i++) {
		if (vs[i]-ra < 0) continue;
		int leftmost = lower_bound(vs+1,vs+vn+1,maxi(0, vs[i]-rb))-vs;
		int rightmost = upper_bound(vs+1,vs+vn+1,vs[i]-ra)-vs-1;
		int cans = query(1, leftmost, rightmost);
//		cerr << vs[i] << "@" << i << " confirmed [" << leftmost << "," << rightmost << "] = " << cans << "\n"; 
		update(1, i, cans + 1);
	}
	int res = query(1, vn, vn);
	if (res >= INF) cout<<"-1"<<endl;
	else cout<<res<<endl;
	
	return 0;
}
2024/11/23 17:49
加载中...