HDU_1199
根据数据的范围感觉离散化之后暴力染色也是可以的,更好一点的办法就是用线段树优化染色操作,最后将所有的标记都下传到叶子节点之后,再顺序扫一遍各个区间就可以得到结果了。
#include<stdio.h> #include<string.h> #include<algorithm> #define MAXD 4010 #define INF 0x3f3f3f3f int N, tx[MAXD], to[4 * MAXD], X, color[4 * MAXD]; struct List { int x, y, c; }list[MAXD]; void build(int cur, int x, int y) { int mid = x + y >> 1, ls = cur << 1, rs = cur << 1 | 1; if(x == y) { to[cur] = 1; return ; } to[cur] = -1; build(ls, x, mid), build(rs, mid + 1, y); } void init() { int i; char b[5]; for(i = 0; i < N; i ++) { scanf("%d%d%s", &list[i].x, &list[i].y, b); if(b[0] == 'w') list[i].c = 0; else list[i].c = 1; tx[i << 1] = list[i].x - 1, tx[i << 1 | 1] = list[i].y; } std::sort(tx, tx + 2 * N); X = 0; for(i = 1; i < 2 * N; i ++) if(tx[i] != tx[i - 1]) tx[++ X] = tx[i]; build(1, 1, X); } void pushdown(int cur) { if(to[cur] != -1) { to[cur << 1] = to[cur << 1 | 1] = to[cur]; to[cur] = -1; } } void refresh(int cur, int x, int y, int s, int t, int c) { int mid = x + y >> 1, ls = cur << 1, rs = cur << 1 | 1; if(x >= s && y <= t) { to[cur] = c; return ; } pushdown(cur); if(mid >= s) refresh(ls, x, mid, s, t, c); if(mid + 1 <= t) refresh(rs, mid + 1, y, s, t, c); } void down(int cur, int x, int y) { int mid = x + y >> 1, ls = cur << 1, rs = cur << 1 | 1; if(x == y) { color[x] = to[cur]; return; } pushdown(cur); down(ls, x, mid), down(rs, mid + 1, y); } int BS(int x) { int min = 0, mid, max = X; for(;;) { mid = min + max >> 1; if(min == mid) break; if(tx[mid] < x) min = mid; else max = mid; } return mid + 1; } void solve() { int i, ans, lx, rx, lt, rt; for(i = 0; i < N; i ++) refresh(1, 1, X, BS(list[i].x), BS(list[i].y), list[i].c); down(1, 1, X); ans = 0, lt = INF; for(i = 1; i <= X; i ++) { if(color[i] == 0) { lt = std::min(lt, tx[i - 1] + 1), rt = tx[i]; if(rt - lt + 1 > ans) ans = rt - lt + 1, lx = lt, rx = rt; } else lt = INF; } if(ans == 0) printf("Oh, my god\n"); else printf("%d %d\n", lx, rx); } int main() { while(scanf("%d", &N) == 1) { init(); solve(); } return 0; }