数据结构专题测试 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 }
posted @ 2017-04-05 17:31  阿波罗2003  阅读(178)  评论(0编辑  收藏  举报