[题解]线段树专题测试2017.1.21

Posted 阿波罗2003

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[题解]线段树专题测试2017.1.21相关的知识,希望对你有一定的参考价值。


  很单纯的一道线段树题。稍微改一下pushDown()就行了。

Code(线段树模板竟然没超100行)

  1 #include<iostream>
  2 #include<sstream>
  3 #include<cstdio>
  4 #include<cmath>
  5 #include<cstdlib>
  6 #include<cstring>
  7 #include<cctype>
  8 #include<queue>
  9 #include<set>
 10 #include<map>
 11 #include<stack>
 12 #include<vector>
 13 #include<algorithm>
 14 using namespace std;
 15 typedef bool boolean;
 16 #ifdef    WIN32
 17 #define AUTO "%I64d"
 18 #else
 19 #define AUTO "%lld"
 20 #endif
 21 #define smin(a, b) (a) = min((a), (b))
 22 #define smax(a, b) (a) = max((a), (b))
 23 template<typename T>
 24 inline void readInteger(T& u){
 25     char x;
 26     int aFlag = 1;
 27     while(!isdigit((x = getchar())) && x != \'-\');
 28     if(x == \'-\'){
 29         aFlag = -1;
 30         x = getchar();
 31     }
 32     for(u = x - \'0\'; isdigit((x = getchar())); u = u * 10 + x - \'0\');
 33     ungetc(x, stdin);
 34     u *= aFlag;
 35 }
 36 
 37 typedef class SegTreeNode {
 38     public:
 39         long long sum;
 40         int l, r;
 41         SegTreeNode *left, *right;
 42         int lazy;
 43         SegTreeNode():sum(0), l(0), r(0), left(NULL), right(NULL), lazy(0){        }
 44         SegTreeNode(int l, int r):sum(0), l(l), r(r), left(NULL), right(NULL), lazy(0){        }
 45         
 46         inline void pushUp(){
 47             this->sum = this->left->sum + this->right->sum;
 48         }
 49         
 50         inline void pushDown(){
 51             left->sum = (left->r - left->l + 1) * 1LL * lazy;
 52             left->lazy = lazy;
 53             right->sum = (right->r - right->l + 1) * 1LL * lazy;
 54             right->lazy = lazy;
 55             lazy = 0;
 56         }
 57 }SegTreeNode;
 58 
 59 typedef class SegTree {
 60     public:
 61         SegTreeNode* root;
 62         
 63         SegTree():root(NULL){        }
 64         SegTree(int size, int* list){
 65             build(root, 1, size, list);
 66         }
 67         
 68         void build(SegTreeNode*& node, int l, int r, int* list){
 69             node = new SegTreeNode(l, r);
 70             if(l == r){
 71                 node->sum = list[l];
 72                 return;
 73             }
 74             int mid = (l + r) >> 1;
 75             build(node->left, l, mid, list);
 76             build(node->right, mid + 1, r, list);
 77             node->pushUp();
 78         }
 79         
 80         void update(SegTreeNode*& node, int l, int r, long long val){
 81             if(node->l == l && node->r == r){
 82                 node->sum = (r - l + 1) * val;
 83                 node->lazy = val;
 84                 return;
 85             }
 86             if(node->lazy)    node->pushDown();
 87             int mid = (node->l + node->r) >> 1;
 88             if(r <= mid)    update(node->left, l, r, val);
 89             else if(l > mid)    update(node->right, l, r, val);
 90             else{
 91                 update(node->left, l, mid, val);
 92                 update(node->right, mid + 1, r, val);
 93             }
 94             node->pushUp();
 95         }
 96         
 97         long long query(SegTreeNode*& node, int l, int r){
 98             if(node->l == l && node->r == r){
 99                 return node->sum;
100             }
101             if(node->lazy)    node->pushDown();
102             int mid = (node->l + node->r) >> 1;
103             if(r <= mid)    return query(node->left, l, r);
104             if(l > mid)        return query(node->right, l, r);
105             return query(node->left, l, mid) + query(node->right, mid + 1, r);
106         }
107 }SegTree;
108 
109 int n, m;
110 int* list;
111 SegTree st;
112 
113 inline void init(){
114     readInteger(n);
115     list = new int[(const int)(n + 1)];
116     for(int i = 1; i <= n; i++)
117         readInteger(list[i]);
118     readInteger(m);
119     st = SegTree(n, list);
120 }
121 
122 inline void solve(){
123     char cmd[10];
124     int a, b, c;
125     while(m--){
126         scanf("%s", cmd);
127         readInteger(a);
128         readInteger(b);
129         if(cmd[0] == \'m\'){
130             readInteger(c);
131             st.update(st.root, a, b, c);
132         }else{
133             long long res = st.query(st.root, a, b);
134             printf(AUTO"\\n", res);
135         }
136     }
137 }
138 
139 int main(){
140     freopen("setsum.in", "r", stdin);
141     freopen("setsum.out", "w", stdout);
142     init();
143     solve();
144     return 0;
145 }

  dfs序弄一下然后加一个树状数组/线段树就可以轻松应付后面的操作,然而我不小心在建树的时候,用下标为节点编号进行建树而不是访问时间(这个问题很诡异,看着数组完全不知道在干什么),于是愉快地只有10分。

  用树状数组要快一点,只不过我比较懒,一二题的线段树模板差距不但,粘过来改一下就行了。

Code

  1 #include<iostream>
  2 #include<sstream>
  3 #include<cstdio>
  4 #include<cmath>
  5 #include<cstdlib>
  6 #include<cstring>
  7 #include<cctype>
  8 #include<queue>
  9 #include<set>
 10 #include<map>
 11 #include<stack>
 12 #include<vector>
 13 #include<algorithm>
 14 using namespace std;
 15 typedef bool boolean;
 16 #ifdef    WIN32
 17 #define AUTO "%I64d"
 18 #else
 19 #define AUTO "%lld"
 20 #endif
 21 #define smin(a, b) (a) = min((a), (b))
 22 #define smax(a, b) (a) = max((a), (b))
 23 template<typename T>
 24 inline void readInteger(T& u){
 25     char x;
 26     int aFlag = 1;
 27     while(!isdigit((x = getchar())) && x != \'-\');
 28     if(x == \'-\'){
 29         aFlag = -1;
 30         x = getchar();
 31     }
 32     for(u = x - \'0\'; isdigit((x = getchar())); u = u * 10 + x - \'0\');
 33     ungetc(x, stdin);
 34     u *= aFlag;
 35 }
 36 
 37 typedef class SegTreeNode {
 38     public:
 39         long long sum;
 40         int l, r;
 41         SegTreeNode *left, *right;
 42         SegTreeNode():sum(0), l(0), r(0), left(NULL), right(NULL){        }
 43         SegTreeNode(int l, int r):sum(0), l(l), r(r), left(NULL), right(NULL){        }
 44         inline void pushUp(){
 45             this->sum = this->left->sum + this->right->sum;
 46         }
 47 }SegTreeNode;
 48 
 49 typedef class SegTree {
 50     public:
 51         SegTreeNode* root;
 52         
 53         SegTree():root(NULL){        }
 54         SegTree(int size, int* list, int* keyer){
 55             build(root, 1, size, list, keyer);
 56         }
 57         
 58         void build(SegTreeNode*& node, int l, int r, int* list, int* keyer){
 59             node = new SegTreeNode(l, r);
 60             if(l == r){
 61                 node->sum = list[keyer[l]];
 62                 return;
 63             }
 64             int mid = (l + r) >> 1;
 65             build(node->left, l, mid, list, keyer);
 66             build(node->right, mid + 1, r, list, keyer);
 67             node->pushUp();
 68         }
 69         
 70         void update(SegTreeNode*& node, int index, long long val){
 71             if(node->l == index && node->r == index){
 72                 node->sum += val;
 73                 return;
 74             }
 75             int mid = (node->l + node->r) >> 1;
 76             if(index <= mid)    update(node->left, index, val);
 77             else update(node->right, index, val);
 78             node->pushUp();
 79         }
 80         
 81         long long query(SegTreeNode*& node, int l, int r){
 82             if(node->l == l && node->r == r){
 83                 return node->sum;
 84             }
 85             int mid = (node->l + node->r) >> 1;
 86             if(r <= mid)    return query(node->left, l, r);
 87             if(l > mid)        return query(node->right, l, r);
 88             return query(node->left, l, mid) + query(node->right, mid + 1, r);
 89         }
 90 }SegTree;
 91 
 92 typedef class Edge{
 93     public:
 94         int end;
 95         int next;
 96         Edge(const int end = 0, const int next = 0):end(end), next(next){        }
 97 }Edge;
 98 
 99 typedef class MapManager{
100     public:
101         int ce;
102         int *h;
103         Edge* edges;
104         MapManager():ce(0), h(NULL), edges(NULL){        }
105         MapManager(int points, int limits):ce(0){
106             h = new int[(const int)(points + 1)];
107             edges = new Edge[(const int)(limits + 1)];
108             memset(h, 0, sizeof(int) * (points + 1));
109         }
110         inline void addEdge(int from, int end){
111             edges[++ce] = Edge(end, h[from]);
112             h[from] = ce;
113         }
114         inline void addDoubleEdge(int from, int end){
115             addEdge(from, end);
116             addEdge(end, from);
117         }
118         Edge& operator [](int pos){
119             return edges[pos];
120         }
121 }MapManager;
122 
123 #define m_begin(g, i) (g).h[(i)]
124 
125 int n, m;
126 int cnt = 0;
127 int* list;
128 int* keyer;
129 int* visitID;
130 int* exitID;
131 SegTree st;
132 MapManager g;
133 
134 void dfs(int node, int last){
135     visitID[node] = ++cnt;
136     keyer[cnt] = node;
137     for(int i = m_begin(g, node); i != 0; i = g[i].next){
138         int &e = g[i].end;
139         if(e == last)    continue;
140         dfs(e, node);
141     }
142     exitID[node] = cnt;
143 }
144 
145 inline void init(){
146     readInteger(n);
147     list = new int[(const int)(n + 1)];
148     g = MapManager(n, n * 2);
149     for(int i = 1; i <= n; i++)
150         readInteger(list[i]);
151     for(int i = 1, a, b; i < n; i++){
152         readInteger(a);
153         readInteger(b);
154         g.addDoubleEdge(a, b);
155     }
156     visitID = new int[(const int)(n + 1)];
157     exitID = new int[(const int)(n + 1)];
158     keyer = new int[(const int)(n + 1)];
159     dfs(1, 0);
160     readInteger(m);
161     st = SegTree(n, list, keyer);
162 }
163 
164 inline void solve(){
165     char cmd[10];
166     int a, b;
167     while(m--){
168         scanf("%s", cmd);
169         readInteger(a);
170         if(cmd[0] == \'m\'){
171             readInteger(b);
172             st.update(st.root, visitID[a], b);
173         }else{
174             long long res = st.query(st.root, visitID[a], exitID[a]);
175             printf(AUTO"\\n", res);
176         }
177     }
178 }
179 
180 int main(){
181     freopen("subtree.in", "r", stdin);
182     freopen("subtree.out", "w", stdout);
183     init();
184     solve();
185     return 0;
186 }

 


  不过我并没有写st表,而是一种很粗暴的方法——树套树(据说线段树套线段树特别牛逼)。

  一个线段树负责一行的最大公约数。套外面的线段树就负责合并列的线段树。还有可以加优化,查询的时候,查到的值为1,就return 1。实测效果不错,综合下来,windows随机数据才0.8s。(然而诡异的cena需要1.9s,指针户吃亏啊。。。)

Code(初次树套树比平衡树短)

  1 #include<iostream>
  2 #include<sstream>
  3 #include<cstdio>
  4 #include<cmath>
  5 #include<cstdlib>
  6 #include<cstring>
  7 #include<cctype>
  8 #include<queue>
  9 #include<set>
 10 #include<map>
 11 #include<stack>
 12 #include<vector>
 13 #include<algorithm>
 14 #include<ctime>
 15 using namespace std;
 16 typedef bool boolean;
 17 #ifdef    WIN32
 18 #define AUTO "%I64d"
 19 #else
 20 #define AUTO "%lld"
 21 #endif
 22 #define smin(a, b) (a) = min((a), (b))
 23 #define smax(a, b) (a) = max((a), (b))
 24 template<typename T>
 25 inline void readInteger(T& u){
 26     char x;
 27     int aFlag = 1;
 28     while(!isdigit((x = getchar())) && x != \'-\');
 29     if(x == \'-\'){
 30         aFlag = -1;
 31         x = getchar();
 32     }
 33     for(u = x - \'0\'; isdigit((x = getchar())); u = u * 10 + x - \'0\');
 34     ungetc(x, stdin);
 35     u *= aFlag;
 36 }
 37 
 38 template<typename T>
 39 inline T gcd(T a, T b){
 40     return (b == 0) ? (a) : (gcd(b, a % b));
 41 }
 42 
 43 template<typename T>
 44 class Matrix{
 45     public:
 46         T* p;
 47         int lines, rows;
 48         Matrix():p(NULL), lines(0), rows(0){        }
 49         Matrix(int rows, int lines):rows(rows), lines(lines){
 50             p = new T[rows * lines];
 51         }
 52         T* operator [](int pos){
 53             return p + pos * lines;
 54         }
 55 };
 56 
 57 typedef class SegTreeNode1{
 58     public:
 59         int val;
[kuangbin] 专题13 基础计算几何 题解 + 总结

培训补坑(day7:线段树的区间修改与运用)(day6是测试,测试题解以后补坑QAQ)

线段树专题—ZOJ1610 Count the Colors

暑假集训8.7数据结构专题-线段树存直线

线段树专题

线段树专题