Mayor's posters
Description
给出n张海报,每张海报的起点终点为l,r。
求依次贴在墙面后最终能看到的海报数。
Solution
由于海报贴的起点终点较大,但总的海报数较少,首先将海报的起点终点离散化。
不过普通离散化还有一些问题(wa了很久),如这个测试点
$3$
$1 10$
$1 3$
$6 10$
普通离散化后的对应关系为$1:1,3:2,6:3,10:4$
这样的话就会将$1 10$区间完全覆盖住,但实际上是不会的
解决这个冲突的办法是在相邻且相差大于1的节点中间再加入一个值。
离散化的问题解决后,就可以开数据结构搞了,不过在下憨憨用的是暴力分块。
和线段树一样记录一个lazy标记,在更改整个区间时下传标记。
最后统计答案。

1 #include <algorithm> 2 #include <cctype> 3 #include <cmath> 4 #include <cstdio> 5 #include <cstdlib> 6 #include <cstring> 7 #include <iostream> 8 #include <map> 9 #include <numeric> 10 #include <queue> 11 #include <set> 12 #include <stack> 13 #if __cplusplus >= 201103L 14 #include <unordered_map> 15 #include <unordered_set> 16 #endif 17 #include <vector> 18 #define lson rt << 1, l, mid 19 #define rson rt << 1 | 1, mid + 1, r 20 #define LONG_LONG_MAX 9223372036854775807LL 21 #define pblank putchar(' ') 22 #define ll LL 23 #define fastIO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0) 24 using namespace std; 25 typedef long long ll; 26 typedef long double ld; 27 typedef unsigned long long ull; 28 typedef pair<int, int> P; 29 const int maxn = 1e4 + 10; 30 int n, m, k, block_num, block_size, cnt; 31 vector<int> v; 32 int lft[maxn], rgt[maxn]; 33 int vis[maxn << 2]; 34 int cd[maxn << 2]; 35 struct Node 36 { 37 int l, r, lazy; 38 } tr[maxn]; 39 inline int getid(int x) 40 { 41 return lower_bound(v.begin(), v.end(), x) - v.begin() + 1; 42 } 43 inline int getblock(int x) 44 { 45 int h = 1, t = block_num, res = -1; 46 while (h <= t) 47 { 48 int mid = h + t >> 1; 49 if (tr[mid].l <= x) 50 { 51 res = mid; 52 h = mid + 1; 53 } 54 else 55 t = mid - 1; 56 } 57 return res; 58 } 59 60 void build(int cnt) 61 { 62 block_size = (int)sqrt(cnt); 63 block_num = cnt / block_size; 64 if (cnt % block_size) 65 block_num = block_size + 1; 66 for (int i = 1; i <= block_num; i++) 67 { 68 tr[i].l = (i - 1) * block_size + 1; 69 tr[i].r = i * block_size; 70 tr[i].lazy = 0; 71 } 72 tr[block_num].r = cnt; 73 } 74 void push_down(int rt) 75 { 76 if (tr[rt].lazy) 77 { 78 for (int i = tr[rt].l; i <= tr[rt].r; i++) 79 cd[i] = tr[rt].lazy; 80 tr[rt].lazy = 0; 81 } 82 } 83 inline void update(int L, int R, int idx) 84 { 85 int bl = getblock(L); 86 int br = getblock(R); 87 if (bl == br || bl + 1 == br) 88 { 89 push_down(bl); 90 if (bl + 1 == br) 91 push_down(br); 92 for (int i = L; i <= R; i++) 93 cd[i] = idx; 94 } 95 else 96 { 97 push_down(bl); 98 push_down(br); 99 for (int i = L; i <= tr[bl].r; i++) 100 cd[i] = idx; 101 for (int i = tr[br].l; i <= R; i++) 102 cd[i] = idx; 103 for (int i = bl + 1; i < br; i++) 104 tr[i].lazy = idx; 105 } 106 } 107 108 int main(int argc, char const *argv[]) 109 { 110 #ifndef ONLINE_JUDGE 111 freopen("in.txt", "r", stdin); 112 // freopen("out.txt", "w", stdout); 113 #endif 114 fastIO; 115 int t; 116 cin >> t; 117 while (t--) 118 { 119 v.clear(); 120 cin >> n; 121 memset(vis, 0, sizeof(int) * (n + 1)); 122 for (int i = 1; i <= n; i++) 123 { 124 cin >> lft[i] >> rgt[i]; 125 v.push_back(lft[i]); 126 v.push_back(rgt[i]); 127 } 128 sort(v.begin(), v.end()); 129 v.erase(unique(v.begin(), v.end()), v.end()); 130 int tmp = v.size(); 131 for (int i = 1; i < tmp; i++) 132 if (v[i] - v[i - 1] > 1) 133 v.push_back(v[i - 1] + 1); 134 sort(v.begin(), v.end()); 135 cnt = v.size(); 136 build(cnt); 137 memset(cd, 0, sizeof(int) * (cnt + 1)); 138 for (int i = 1; i <= n; i++) 139 { 140 int l = getid(lft[i]); 141 int r = getid(rgt[i]); 142 update(l, r, i); 143 } 144 for (int i = 1; i <= block_num; i++) 145 { 146 if (tr[i].lazy) 147 vis[tr[i].lazy] = 1; 148 else 149 { 150 for (int j = tr[i].l; j <= tr[i].r; j++) 151 if (cd[j]) 152 vis[cd[j]] = 1; 153 } 154 } 155 cout << accumulate(vis + 1, vis + 1 + cnt, 0) << " "; 156 } 157 return 0; 158 }