Codeforces 750E segment tree DP

Meaning of the questions: to give you a string, there are two: 1: change the character of a location. 2: Inquiry l to r substring minimum number of characters to be deleted, making the substring containing the sequence 2017, and not 2016 sequence?

Thinking: tree segment DP, we set the state of 0, 1, 2, 3, 4 are: null, 2, 20, minimum cost 201, 2017, we use the cross-dimension segment tree to take a state transition matrix, combined with two adjacent sub-string, when direct transfer to.

Code:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ls (o << 1)
#define rs (o << 1 | 1)
using namespace std;
const int maxn = 200010;
int a[maxn];
char s[maxn];
struct node {
	int f[5][5];
	void init(int x) {
		for (int i = 0; i < 5; i++) {
			for (int j = 0; j < 5; j++) {
				if(i == j) continue;
				f[i][j] = INF;
			}
		}
		if(x == 2) {
			f[0][0] = 1, f[0][1] = 0;
		} else if (x == 0) {
			f[1][1] = 1, f[1][2] = 0;			
		} else if (x == 1) {
			f[2][2] = 1, f[2][3] = 0;
		} else if (x == 7) {
			f[3][3] = 1, f[3][4] = 0;
		} else if (x == 6) {
			f[3][3] = 1;
			f[4][4] = 1;
		} else if (x == -1){
			for (int i = 0; i < 5; i++)
				f[i][i] = INF;
		} else {
			for (int i = 0; i < 5; i++)
				f[i][i] = 0;
		}
	}
	
	void print() {
		for (int i = 0; i < 5; i++) {
			for (int j = 0; j < 5; j++) {
				if(f[i][j] == INF) printf("inf ");
				else printf("%d ", f[i][j]);
			}
			printf("\n");
		}
	}
};
node tr[maxn * 4];
node merge(node t1, node t2) {
	node ans;
	ans.init(-1);
//	ans.init(-1);
//	printf("ans\n");
//	ans.print();
//	printf("t1\n");
//	t1.print();
//	printf("t2\n");
//	t2.print();
	for (int i = 0; i < 5; i++) {
		for (int j = i; j < 5; j++) {
			for (int k = i; k <= j; k++) {
				ans.f[i][j] = min(ans.f[i][j], t1.f[i][k] + t2.f[k][j]); 
			}
		}
	}
//	printf("ans\n");
//	ans.print();
	return ans;
}
void build(int o, int l, int r) {
	if(l == r) {
		tr[o].init(a[l]);
		return;
	}
	int mid = (l + r) >> 1;
	build(ls, l, mid);
	build(rs, mid + 1, r);
	tr[o] = merge(tr[ls], tr[rs]);
}
void update(int o, int l, int r, int ql, int qr, int val) {
	if(l == r) {
		tr[o].init(val);
		return;
	}
	int mid = (l + r) >> 1;
	if(ql <= mid) update(ls, l, mid, ql, qr, val);
	if(qr > mid) update(rs, mid + 1, r, ql, qr, val);
	tr[o] = merge(tr[ls], tr[rs]);
}
node query(int o, int l, int r, int ql, int qr) {
	if(l >= ql && r <= qr) {
		return tr[o];
	}
	int mid = (l + r) >> 1;
	node ans;
	ans.init(-1);
	if(ql <= mid && qr > mid) ans = merge(query(ls, l, mid, ql, qr), query(rs, mid + 1, r, ql, qr));
	else if(ql <= mid) ans = query(ls, l, mid, ql, qr);
	else if(qr > mid) ans = query(rs, mid + 1, r, ql, qr);
	return ans; 
}
int main() {
	int n, m, l, r;
	scanf("%d%d", &n, &m);
	scanf("%s", s + 1);
	for (int i = 1; i <= n; i++) {
		a[i] = s[i] - '0';
	}
	build(1, 1, n);
	for (int i = 1; i <= m; i++) {
		scanf("%d%d", &l, &r);
		node ans = query(1, 1, n, l, r);
		if(ans.f[0][4] == INF) printf("-1\n");
		else printf("%d\n", ans.f[0][4]);
	}
} 

  

Guess you like

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