数据结构专题测试 2017.4.4 - 线段树
打两个lazy标记,覆盖操作(modify),把mlazy改为x,clazy改为0,增加操作(change),把clazy增加x。pushDown时候先更新mlazy,再更新clazy。
但是数据有些问题(然后十个点全崩掉了),l > r的情况修改操作无视,查询操作输出0。
Code
1 #include<iostream> 2 #include<cstdio> 3 #include<ctime> 4 #include<cctype> 5 #include<cstring> 6 #include<cstdlib> 7 #include<fstream> 8 #include<sstream> 9 #include<algorithm> 10 #include<map> 11 #include<set> 12 #include<stack> 13 #include<queue> 14 #include<vector> 15 #include<stack> 16 #ifndef WIN32 17 #define AUTO "%lld" 18 #else 19 #define AUTO "%I64d" 20 #endif 21 using namespace std; 22 typedef bool boolean; 23 #define inf 0xfffffff 24 #define llf (1LL << 60) 25 #define smin(a, b) a = min(a, b) 26 #define smax(a, b) a = max(a, b) 27 #define max3(a, b, c) max(a, max(b, c)) 28 #define min3(a, b, c) min(a, min(b, c)) 29 template<typename T> 30 inline boolean readInteger(T& u){ 31 char x; 32 int aFlag = 1; 33 while(!isdigit((x = getchar())) && x != '-' && x != -1); 34 if(x == -1) { 35 ungetc(x, stdin); 36 return false; 37 } 38 if(x == '-'){ 39 x = getchar(); 40 aFlag = -1; 41 } 42 for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0'); 43 ungetc(x, stdin); 44 u *= aFlag; 45 return true; 46 } 47 48 typedef class SegTreeNode { 49 public: 50 long long val; 51 SegTreeNode *l, *r; 52 long long clazy; 53 long long mlazy; 54 SegTreeNode(int val = 0, SegTreeNode* l = NULL, SegTreeNode* r = NULL, long long mlazy = llf, long long clazy = 0):val(val), l(l), r(r), mlazy(mlazy), clazy(clazy) { } 55 56 inline void pushUp() { 57 this->val = l->val + r->val; 58 } 59 60 inline void pushmDown(int le, int ri, int mid) { 61 l->val = (mid - le + 1) * mlazy; 62 r->val = (ri - mid) * mlazy; 63 l->mlazy = r->mlazy = mlazy; 64 l->clazy = r->clazy = 0; 65 mlazy = llf; 66 } 67 68 inline void pushcDown(int le, int ri, int mid) { 69 l->val += (mid - le + 1) * clazy; 70 r->val += (ri - mid) * clazy; 71 l->clazy += clazy, r->clazy += clazy; 72 clazy = 0; 73 } 74 }SegTreeNode; 75 76 typedef class SegTree { 77 public: 78 SegTreeNode* root; 79 80 SegTree():root(NULL) { } 81 SegTree(int s, int* lis) { 82 build(root, 1, s, lis); 83 } 84 85 void build(SegTreeNode*& node, int l, int r, int* lis) { 86 node = new SegTreeNode(); 87 if(l == r) { 88 node->val = lis[l]; 89 return; 90 } 91 int mid = (l + r) >> 1; 92 build(node->l, l, mid, lis); 93 build(node->r, mid + 1, r, lis); 94 node->pushUp(); 95 } 96 97 void modify(SegTreeNode*& node, int l, int r, int ml, int mr, int x) { 98 if(l == ml && r == mr) { 99 node->val = (r - l + 1) * 1LL * x; 100 node->mlazy = x, node->clazy = 0; 101 return; 102 } 103 int mid = (l + r) >> 1; 104 if(node->mlazy != llf) node->pushmDown(l, r, mid); 105 if(node->clazy) node->pushcDown(l, r, mid); 106 if(mr <= mid) modify(node->l, l, mid, ml, mr, x); 107 else if(ml > mid) modify(node->r, mid + 1, r, ml, mr, x); 108 else { 109 modify(node->l, l, mid, ml, mid, x); 110 modify(node->r, mid + 1, r, mid + 1, mr, x); 111 } 112 node->pushUp(); 113 } 114 115 void update(SegTreeNode*& node, int l, int r, int ml, int mr, int x) { 116 if(l == ml && r == mr) { 117 node->val += (r - l + 1) * 1LL * x; 118 node->clazy += x; 119 return; 120 } 121 int mid = (l + r) >> 1; 122 if(node->mlazy != llf) node->pushmDown(l, r, mid); 123 if(node->clazy) node->pushcDown(l, r, mid); 124 if(mr <= mid) update(node->l, l, mid, ml, mr, x); 125 else if(ml > mid) update(node->r, mid + 1, r, ml, mr, x); 126 else { 127 update(node->l, l, mid, ml, mid, x); 128 update(node->r, mid + 1, r, mid + 1, mr, x); 129 } 130 node->pushUp(); 131 } 132 133 long long query(SegTreeNode*& node, int l, int r, int ql, int qr) { 134 if(l == ql && r == qr) { 135 return node->val; 136 } 137 int mid = (l + r) >> 1; 138 if(node->mlazy != llf) node->pushmDown(l, r, mid); 139 if(node->clazy) node->pushcDown(l, r, mid); 140 if(qr <= mid) return query(node->l, l, mid, ql, qr); 141 if(ql > mid) return query(node->r, mid + 1, r, ql, qr); 142 return query(node->l, l, mid, ql, mid) + query(node->r, mid + 1, r, mid + 1, qr); 143 } 144 }SegTree; 145 146 int n, m; 147 int* lis; 148 SegTree st; 149 150 inline void init() { 151 readInteger(n); 152 readInteger(m); 153 lis = new int[(const int)(n + 1)]; 154 for(int i = 1; i <= n; i++) { 155 readInteger(lis[i]); 156 } 157 st = SegTree(n, lis); 158 } 159 160 char s[11]; 161 inline void solve() { 162 int a, b, x; 163 while(m--) { 164 scanf("%s", s); 165 readInteger(a); 166 readInteger(b); 167 if(s[0] == 'm') { 168 readInteger(x); 169 if(a > b) continue; 170 st.modify(st.root, 1, n, a, b, x); 171 } else if(s[0] == 'c') { 172 readInteger(x); 173 if(a > b) continue; 174 st.update(st.root, 1, n, a, b, x); 175 } else { 176 if(a > b) printf("0\n"); 177 else { 178 long long res = st.query(st.root, 1, n, a, b); 179 printf(AUTO"\n", res); 180 } 181 } 182 } 183 } 184 185 int main() { 186 freopen("setmod.in", "r", stdin); 187 freopen("setmod.out", "w", stdout); 188 init(); 189 solve(); 190 return 0; 191 }
将平行于x轴的线段按y值排序,然后扫描线加线段树辅助。
线段树的节点记录cov,sum。cov表示该节点代表的区间被完全覆盖的次数,sum表示在该区间内被覆盖的长度。
更新时先判断cov是否非0,如果是,则sum = r - l + 1,否则用左右子树的值去更新它。
当扫描线扫描到下边界时,将它加入线段树,否则再线段树中将它删除。每次处理完一个y值的边,就给答案加上根节点的sum值乘上和下一条线段的y值的差值。
Code
1 #include<iostream> 2 #include<cstdio> 3 #include<ctime> 4 #include<cctype> 5 #include<cstring> 6 #include<cstdlib> 7 #include<fstream> 8 #include<sstream> 9 #include<algorithm> 10 #include<map> 11 #include<set> 12 #include<stack> 13 #include<queue> 14 #include<vector> 15 #include<stack> 16 #ifndef WIN32 17 #define AUTO "%lld" 18 #else 19 #define AUTO "%I64d" 20 #endif 21 using namespace std; 22 typedef bool boolean; 23 #define inf 0xfffffff 24 #define llf (1LL << 60) 25 #define smin(a, b) a = min(a, b) 26 #define smax(a, b) a = max(a, b) 27 #define max3(a, b, c) max(a, max(b, c)) 28 #define min3(a, b, c) min(a, min(b, c)) 29 template<typename T> 30 inline boolean readInteger(T& u){ 31 char x; 32 int aFlag = 1; 33 while(!isdigit((x = getchar())) && x != '-' && x != -1); 34 if(x == -1) { 35 ungetc(x, stdin); 36 return false; 37 } 38 if(x == '-'){ 39 x = getchar(); 40 aFlag = -1; 41 } 42 for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0'); 43 ungetc(x, stdin); 44 u *= aFlag; 45 return true; 46 } 47 48 typedef class SegTreeNode { 49 public: 50 int cov; //被完整覆盖的次数 51 int sum; //被覆盖的长度 52 SegTreeNode *l, *r; 53 54 SegTreeNode(int cov = 0, int sum = 0, SegTreeNode* l = NULL, SegTreeNode* r = NULL):cov(cov), sum(sum), l(l), r(r) { } 55 56 inline void pushUp(int lg, int rt) { 57 if(cov) sum = rt - lg + 1; 58 else if(lg == rt) sum = 0; 59 else sum = l->sum + r->sum; 60 } 61 }SegTreeNode; 62 63 typedef class SegTree { 64 public: 65 SegTreeNode* root; 66 67 SegTree():root(NULL) { } 68 SegTree(int s) { 69 build(root, 1, s); 70 } 71 72 void build(SegTreeNode*& node, int l, int r) { 73 node = new SegTreeNode(); 74 if(l == r) return; 75 int mid = (l + r) >> 1; 76 build(node->l, l, mid); 77 build(node->r, mid + 1, r); 78 } 79 80 void update(SegTreeNode*& node, int l, int r, int le, int ri, int val) { 81 if(l == le && r == ri) { 82 node->cov += val; 83 node->pushUp(l, r); 84 return; 85 } 86 int mid = (l + r) >> 1; 87 if(ri <= mid) update(node->l, l, mid, le, ri, val); 88 else if(le > mid) update(node->r, mid + 1, r, le, ri, val); 89 else { 90 update(node->l, l, mid, le, mid, val); 91 update(node->r, mid + 1, r, mid + 1, ri, val); 92 } 93 node->pushUp(l, r); 94 } 95 96 int query() { 97 return root->sum; 98 } 99 }SegTree; 100 101 typedef class Line { 102 public: 103 int x0, x1; 104 int y; 105 int side; 106 Line(int x0 = 0, int x1 = 0, int y = 0, int side = 0):x0(x0), x1(x1), y(y), side(side) { } 107 108 boolean operator < (Line b) const { 109 if(y != b.y) return y < b.y; 110 if(x0 != b.x0) return x0 < b.x0; 111 return x1 < b.x1; 112 } 113 }Line; 114 115 int n; 116 Line* lines; 117 int valx = 0, minx = inf; 118 119 inline void init() { 120 readInteger(n); 121 lines = new Line[(2 * n + 1)]; 122 for(int i = 1, x0, x1, y0, y1; i <= n; i++) { 123 readInteger(x0); 124 readInteger(y0); 125 readInteger(x1); 126 readInteger(y1); 127 lines[2 * i - 1] = Line(x0, x1, y0, 1); 128 lines[2 * i] = Line(x0, x1, y1 + 1, -1); 129 smax(valx, x1); 130 } 131 } 132 133 SegTree st; 134 long long res = 0; 135 inline void solve() { 136 st = SegTree(valx + 1); 137 sort(lines + 1, lines + 2 * n + 1); 138 for(int i = 1; i <= 2 * n;) { 139 int cmp = lines[i].y; 140 while(i <= 2 * n && lines[i].y == cmp) { 141 st.update(st.root, 1, valx, lines[i].x0, lines[i].x1, lines[i].side); 142 i++; 143 } 144 res += st.query() * 1LL * (lines[i].y - cmp); 145 } 146 printf(AUTO, res); 147 } 148 149 int main() { 150 freopen("area.in", "r", stdin); 151 freopen("area.out", "w", stdout); 152 init(); 153 solve(); 154 return 0; 155 }
带修改的主席树裸题。
只不过因为数据范围比较大,动态开节点变成了,先开一堆节点然后慢慢分配(此方法被称为开内存池),vector也不能用,手写一个数组,不然会超时。
Code
1 #include<iostream> 2 #include<cstdio> 3 #include<ctime> 4 #include<cctype> 5 #include<cstring> 6 #include<cstdlib> 7 #include<fstream> 8 #include<sstream> 9 #include<algorithm> 10 #include<map> 11 #include<set> 12 #include<stack> 13 #include<queue> 14 #include<vector> 15 #include<stack> 16 #ifndef WIN32 17 #define AUTO "%lld" 18 #else 19 #define AUTO "%I64d" 20 #endif 21 using namespace std; 22 typedef bool boolean; 23 #define inf 0xfffffff 24 #define llf (1LL << 60) 25 #define smin(a, b) a = min(a, b) 26 #define smax(a, b) a = max(a, b) 27 #define max3(a, b, c) max(a, max(b, c)) 28 #define min3(a, b, c) min(a, min(b, c)) 29 template<typename T> 30 inline boolean readInteger(T& u){ 31 char x; 32 int aFlag = 1; 33 while(!isdigit((x = getchar())) && x != '-' && x != -1); 34 if(x == -1) { 35 ungetc(x, stdin); 36 return false; 37 } 38 if(x == '-'){ 39 x = getchar(); 40 aFlag = -1; 41 } 42 for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0'); 43 ungetc(x, stdin); 44 u *= aFlag; 45 return true; 46 } 47 48 typedef class SegTreeNode { 49 public: 50 int s; 51 SegTreeNode *l, *r; 52 SegTreeNode(int s = 0, SegTreeNode* l = NULL, SegTreeNode* r = NULL):s(s), l(l), r(r) { } 53 54 inline void pushUp() { 55 this->s += l->s + r->s; 56 } 57 }SegTreeNode; 58 59 SegTreeNode nul = SegTreeNode(0, &nul, &nul); 60 SegTreeNode *top; 61 SegTreeNode* pool; 62 #define lowbit(x) (x & (-x)) 63 64 template<typename T> 65 class List { 66 public: 67 T* lis; 68 int top; 69 70 List():lis(NULL), top(0) { } 71 List(int s):top(0) { 72 lis = new T[(const int)(s + 1)]; 73 } 74 // ~List() { 75 // delete[] lis; 76 // } 77 78 void push_back(T x) { lis[top++] = x; } 79 int size() { return top; } 80 void clear() { top = 0; } 81 82 T& operator [] (int pos) { 83 return lis[pos]; 84 } 85 }; 86 87 typedef class ChairTree { 88 public: 89 int size; 90 int* a; 91 SegTreeNode** lis; 92 List<SegTreeNode*> sum, csum; 93 List<SegTreeNode*> nodes; 94 95 SegTreeNode* newNode() { 96 top->l = &nul; 97 top->r = &nul; 98 top->s = 0; 99 return top++; 100 } 101 102 ChairTree():size(0) { } 103 ChairTree(int s, int* a):size(s), a(a) { 104 lis = new SegTreeNode*[(const int)(s + 1)]; 105 sum = List<SegTreeNode*>(s + 10); 106 csum = List<SegTreeNode*>(s + 10); 107 nodes = List<SegTreeNode*>(s + 10); 108 for(int i = 0; i <= s; i++) 109 lis[i] = newNode(); 110 for(int i = 1; i <= s; i++) { 111 for(int j = i; j <= size; j += lowbit(j)) 112 modify(lis[j], 1, size, a[i], 1); 113 } 114 } 115 116 void modify(SegTreeNode*& node, int l, int r, int idx, int val) { 117 if(node == &nul) 118 node = newNode(); 119 node->s += val; 120 if(l == idx && r == idx) { 121 return; 122 } 123 int mid = (l + r) >> 1; 124 if(idx <= mid) modify(node->l, l, mid, idx, val); 125 else modify(node->r, mid + 1, r, idx, val); 126 } 127 128 inline void modify(int idx, int x) { 129 for(int i = idx; i <= size; i += lowbit(i)) modify(lis[i], 1, size, a[idx], -1); 130 a[idx] = x; 131 for(int i = idx; i <= size; i += lowbit(i)) modify(lis[i], 1, size, a[idx], 1); 132 } 133 134 int query(List<SegTreeNode*>& sum, List<SegTreeNode*>& csum, int l, int r, int k) { 135 if(l == r) return l; 136 int mid = (l + r) >> 1; 137 int s1 = sum.size(), s2 = csum.size(); 138 int ls = 0; 139 for(int i = 0; i < s1; i++) ls += sum[i]->l->s; 140 for(int i = 0; i < s2; i++) ls -= csum[i]->l->s; 141 if(k <= ls) { 142 for(int i = 0; i < s1; i++) sum[i] = sum[i]->l; 143 for(int i = 0; i < s2; i++) csum[i] = csum[i]->l; 144 return query(sum, csum, l, mid, k); 145 } 146 for(int i = 0; i < s1; i++) sum[i] = sum[i]->r; 147 for(int i = 0; i < s2; i++) csum[i] = csum[i]->r; 148 return query(sum, csum, mid + 1, r, k - ls); 149 } 150 151 int query(int l, int r, int k) { 152 sum.clear(), csum.clear(); 153 for(int i = r; i; i -= lowbit(i)) sum.push_back(lis[i]); 154 for(int i = l - 1; i; i -= lowbit(i)) csum.push_back(lis[i]); 155 return query(sum, csum, 1, size, k); 156 } 157 }ChairTree; 158 159 int n, m; 160 int* lis; 161 ChairTree ct; 162 163 inline void init() { 164 readInteger(n); 165 readInteger(m); 166 lis = new int[(const int)(n + 1)]; 167 for(int i = 1; i <= n; i++) 168 readInteger(lis[i]); 169 } 170 171 char s[10]; 172 inline void solve() { 173 pool = new SegTreeNode[(n * 200)]; 174 top = pool; 175 int a, b, c; 176 ct = ChairTree(n, lis); 177 while(m--) { 178 scanf("%s", s); 179 readInteger(a); 180 readInteger(b); 181 if(s[0] == 'm') { 182 ct.modify(a, b); 183 } else { 184 readInteger(c); 185 int x = ct.query(a, b, c); 186 printf("%d\n", x); 187 } 188 } 189 } 190 191 int main() { 192 freopen("intkth.in", "r", stdin); 193 freopen("intkth.out", "w", stdout); 194 init(); 195 solve(); 196 return 0; 197 }