题意略去。
考虑给定的R对pair(A, B)。
即A能看见B,这意味着B不比A低,并且区间内部的所有元素的高度严格小于A的高度。
我们规定区间的方向:若A > B,为反方向,反之称为正方向。
容易发现,区间在同一方向上不交叉,即要么相离,要么相互包含。
在相反反方向上,若两区间不相互包含,必定是有且仅有一个公共区间端点。
首先将所有idx上的高度默认设置为H。
对于相离的区间,他们之间的计算是独立的。
考虑相互包含的区间,先考虑范围最大的那个区间,处理之间闭区间[A,B]上的高度是相同的,满足此条件只需令(A,B)区间内元素自减一。
递归考虑其包含的区间,显然这样的做法是最优的且合法的。
实际上这与考虑区间的次序无关。
即每得到一个区间,对开区间内的元素减一即可。
可以用线段树来做区间的修改操作。
http://poj.org/problem?id=3263
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <set> 5 using namespace std; 6 const int maxn = 1e4 + 10; 7 set< pair<int, int> > S; 8 struct Seg{ 9 int l, r, h; 10 int lazy; 11 }seg[maxn << 2]; 12 int n, m, I, H; 13 14 void build(int u, int l, int r){ 15 seg[u].l = l; 16 seg[u].r = r; 17 seg[u].lazy = 0; 18 seg[u].h = H; 19 if(r - l < 2) return; 20 int mid = (l + r) >> 1; 21 build(u << 1, l, mid); 22 build(u << 1 | 1, mid, r); 23 } 24 25 void push_down(int u){ 26 if(seg[u].lazy > 0 && seg[u].r - seg[u].l > 1){ 27 int mid = (seg[u].l + seg[u].r) >> 1; 28 seg[u << 1].lazy += seg[u].lazy; 29 seg[u << 1 | 1].lazy += seg[u].lazy; 30 seg[u << 1].h -= seg[u].lazy; 31 seg[u << 1 | 1].h -= seg[u].lazy; 32 seg[u].lazy = 0; 33 } 34 } 35 36 void update(int u, int l, int r, int L, int R){ 37 if(R - L < 1) return; 38 if(L == l && r == R){ 39 seg[u].lazy++; 40 seg[u].h--; 41 return; 42 } 43 push_down(u); 44 int mid = (l + r) >> 1; 45 if(R <= mid) update(u << 1, l, mid, L, R); 46 else if(L >= mid) update(u << 1 | 1, mid, r, L, R); 47 else{ 48 update(u << 1, l, mid, L, mid); 49 update(u << 1 | 1, mid, r, mid, R); 50 } 51 } 52 53 void query(int u, int l, int r){ 54 if(r - l == 1){ 55 printf("%d ", seg[u].h); 56 return; 57 } 58 push_down(u); 59 int mid = (l + r) >> 1; 60 query(u << 1, l, mid); 61 query(u << 1 | 1, mid, r); 62 } 63 64 int main(){ 65 while(~scanf("%d%d%d%d", &n, &I, &H, &m)){ 66 build(1, 1, n + 1); 67 S.clear(); 68 for(int i = 0, u, v; i < m; i++){ 69 scanf("%d%d", &u, &v); 70 if(u == v || S.find(make_pair(u, v)) != S.end()) continue; 71 S.insert(make_pair(u, v)); 72 if(u > v) swap(u, v); 73 update(1, 1, n + 1, u + 1, v); 74 } 75 query(1, 1, n + 1); 76 } 77 return 0; 78 }