Codeforces 1197E Culture Code DP

Meaning of the questions: Do you have n matryoshka, known volume and volume of each set of her, and asked how many subsets of the following conditions are met:

1: This is a subset of a subset great, that can not be added to the other set of her in this subset.

2: a gap between the doll and the minimum subset.

Thinking 1: Optimization segment tree DP:

The doll according to the first volume of a first priority, the second priority volume, small to large. Provided ans [i] .second the i th doll in the outermost layer, the smallest maximum number of sub-interval set, ans [i] .first minimum clearance, we performed transfer: Suppose the i-th doll r is the volume, larger than the volume of the volume of a doll r is l1, the volume is r1, so easy to find all volume [l1, r1 - 1] doll range may shift from the current state. We can be performed by a special tree line marks the transfer, I'm online segment tree maintains three markers: volume, minimum clearance number. When lazy updating flag, determines the minimum clearance decentralized - if the current volume to less than. Such a single point of the segment tree query can be obtained the corresponding DP status.

Code:

#include <bits/stdc++.h>
#define LL long long
#define pLL pair<LL, LL>
#define pii pair<int, int>
#define ls (o << 1)
#define rs (o << 1 | 1)
using namespace std;
const int maxn = 200010;
const LL mod = 1000000007;
pii a[maxn];
int val[maxn];
struct Seg {
	pLL lz;
	int pos;
};
Seg tr[maxn * 4];
pLL ans[maxn];
bool v[maxn];
void maintain(int o, pLL tmp, int p) {
	if(tmp.first - p < tr[o].lz.first - tr[o].pos) {
		tr[o].lz = tmp, tr[o].pos = p;
	} else if(tmp.first - p == tr[o].lz.first - tr[o].pos) {
		tr[o].lz.second = (tr[o].lz.second + tmp.second) % mod;
	}
}
void pushdown(int o) {
	if(tr[o].lz.second != 0) {
		maintain(ls, tr[o].lz, tr[o].pos);
		maintain(rs, tr[o].lz, tr[o].pos);
		tr[o].lz = make_pair(1e18, 0ll);
		tr[o].pos = 0;
	}
}
void build(int o, int l, int r) {
	if(l == r) {
		if(val[l]) {
			tr[o].lz = make_pair(0, val[l]);
			tr[o].pos = 0;
		} else {
			tr[o].lz = make_pair(1e18, 0);
			tr[o].pos = 0;
		}
		return;
	}
	tr[o].lz = make_pair(1e18, 0);
	tr[o].pos = 0;
	int mid = (l + r) >> 1;
	build(ls, l, mid);
	build(rs, mid + 1, r);
}
pLL query(int o, int l, int r, int p) {
	if(l == r) {
		ans[l] = make_pair(tr[o].lz.first + a[l].first - tr[o].pos, tr[o].lz.second);
		return ans[l];
	}
	pushdown(o);
	int mid = (l + r) >> 1;
	if(p <= mid) return query(ls, l, mid, p);
	else return query(rs, mid + 1, r, p);
}
void update(int o, int l, int r, int ql, int qr, int p, pLL tmp) {
	if(l >= ql && r <= qr) {
		maintain(o, tmp, p);
		return;
	}
	pushdown(o);
	int mid = (l + r) >> 1;
	if(ql <= mid) update(ls, l, mid, ql, qr, p, tmp);
	if(qr > mid) update(rs, mid + 1, r, ql, qr, p, tmp);
}
int main() {
	int n;
	LL mi = 1e18;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%d%d", &a[i].second, &a[i].first);
	}
	sort(a + 1, a + 1 + n);
	for (int i = 1; i <= n; i++) {
		if(a[i].first >= mi) break;
		val[i] = 1;
		mi = min(mi, (LL)a[i].second);
	}
	build(1, 1, n);
	mi = 1e18;
	for (int i = 1; i <= n; i++) {
		pLL tmp = query(1, 1, n, i);
		ans[i] = tmp;
		int pos1 = lower_bound(a + 1, a + 1 + n, make_pair(a[i].second, a[i].second)) - a;
		int pos2 = lower_bound(a + 1, a + 1 + n, make_pair(a[pos1].second, a[pos1].second)) - a - 1;
		if(pos1 <= n) 
			update(1, 1, n, pos1, pos2, a[i].second, tmp);
		if(pos1 <= n) {
			v[i] = 1;
		}
	}
	for (int i = 1; i <= n; i++) {
		if(v[i]) continue;
		mi = min(mi, ans[i].first);
	}
	LL res = 0;
	for (int i = 1; i <= n; i++) {
		if(v[i]) continue;
		if(ans[i].first == mi) res = (res + ans[i].second) % mod;
	}
	printf("%lld\n", res);
}

2 :( ideas from PinkRabbit) although they would just practice before, but the nature of the subject is not completely excavated. We shift in thinking about: state we wish to look at what the state may be transferred to the current state, easily found after sorting can be transferred to the current state of a prefix, then we two pointer This approach can be used at the time of transfer. So the new question is, how do you know which of these prefixes state can truly be transferred to the current state? Set f [i] is the i-th doll minimum clearance, ANS [i] is the number of minimum clearance, A [i] is the i-th set of her volume, B [i] is the volume, then those prefixes most state (assumed to be the state t), f [t] - a [t] may be transferred only minimal state as the current state. Therefore, in the process of just two pointers maintained f [t] - a [t] to a minimum, and then perform the transfer.

Code:

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 200010;
const LL mod = 1000000007;
int a[maxn], b[maxn], p1[maxn], p2[maxn];
LL ans[maxn];
int f[maxn];
bool cmp1(int x, int y) {
	return a[x] < a[y];
}
bool cmp2(int x, int y) {
	return b[x] < b[y];
}
int main() {
	int n, ed = -1;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%d%d", &a[i], &b[i]);
		p1[i] = p2[i] = i;
		ed = max(ed, b[i]);
	}
	sort(p1 + 1, p1 + 1 + n, cmp1);
	sort(p2 + 1, p2 + 1 + n, cmp2);
	int pos = 1;
	int mi = 0, sum = 1;
	for (int i = 1; i <= n; i++) {
		int now = p2[i];
		while(pos <= n && a[p1[pos]] <= b[now]) {
			int t = p1[pos];
			if(f[t] - a[t] < mi) {
				mi = f[t] - a[t];
				sum = ans[t];
			} else if(f[t] - a[t] == mi) {
				sum = (sum + ans[t]) % mod;
			}
			pos++;
		}
		f[now] = b[now] + mi;
		ans[now] = sum;
	}
	LL res = 0;
	mi = 1e9;
	for (int i = 1; i <= n; i++) {
		if(a[i] <= ed) continue;
		if(f[i] < mi) {
			mi = f[i];
			res = ans[i];
		} else if(f[i] == mi) {
			res = (res + ans[i]) % mod;
		}
	}
	printf("%lld\n", res);
}

  

Guess you like

Origin www.cnblogs.com/pkgunboat/p/11231288.html