求LCA练习+部分算法复习 2017.1.22


  第一题就LCA即可。不过推荐用Tarjan(最快,常数很小)。然后Tarjan的时候顺便就出一个dist[i],表示i节点到根节点的距离。求出了LCA,那么两点间的距离就为dist[u] + dist[v] - 2 * dist[lca]。

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 #ifndef    WIN32
 15 #define    AUTO "%I64d"
 16 #else
 17 #define AUTO "%lld"
 18 #endif
 19 using namespace std;
 20 typedef bool boolean;
 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 Edge {
 38     public:
 39         int end;
 40         int next;
 41         int w;
 42         Edge(const int end = 0, const int next = 0, const int w = 0):end(end), next(next), w(w){        }
 43 }Edge;
 44 
 45 typedef class MapManager{
 46     public:
 47         int ce;
 48         Edge* edges;
 49         int* h;
 50         MapManager():ce(0), edges(NULL), h(NULL){        }
 51         MapManager(int points, int limit):ce(0){
 52             edges = new Edge[(const int)(limit + 1)];
 53             h = new int[(const int)(points + 1)];
 54             memset(h, 0, sizeof(int) * (points + 1));
 55         }
 56         inline void addEdge(int from, int end, int w){
 57             edges[++ce] = Edge(end, h[from], w);
 58             h[from] = ce;
 59         }
 60         inline void addDoubleEdge(int from, int end, int w){
 61             addEdge(from, end, w);
 62             addEdge(end, from, w);
 63         }
 64         Edge& operator [](int pos){
 65             return edges[pos];
 66         }
 67 }MapManager;
 68 #define m_begin(g, i) (g).h[(i)]
 69 
 70 typedef class union_found{
 71     public:
 72         int *f;
 73         union_found():f(NULL) {}
 74         union_found(int points) {
 75             f = new int[(const int)(points + 1)];
 76         }
 77         int find(int x) {
 78             if(f[x] != x)    return f[x] = find(f[x]);
 79             return f[x];
 80         }
 81         void unit(int fa, int so) {
 82             int ffa = find(fa);
 83             int fso = find(so);
 84             f[fso] = ffa;
 85         }
 86         int& operator [](int pos){
 87             return f[pos];
 88         }
 89 }union_found;
 90 
 91 int n, m;
 92 MapManager g;
 93 MapManager q;
 94 int *results;
 95 boolean* enable;
 96 int *querya, *queryb;
 97 union_found uf;
 98 boolean* visited;
 99 int* dist;
100 
101 inline void init(){
102     readInteger(n);
103     g = MapManager(n, 2 * n);
104     for(int i = 1, a, b, c; i < n; i++){
105         readInteger(a);
106         readInteger(b);
107         readInteger(c);
108         g.addDoubleEdge(a, b, c);
109     }
110     readInteger(m);
111     q = MapManager(n, 2 * m);
112     querya = new int[(const int)(m + 1)];
113     queryb = new int[(const int)(m + 1)];
114     results = new int[(const int)(m + 1)];
115     enable = new boolean[(const int)(m + 1)];
116     dist = new int[(const int)(n + 1)];
117     uf = union_found(n);
118     visited = new boolean[(const int)(n + 1)];
119     memset(visited, false, sizeof(boolean) * (n + 1));
120     memset(enable, true, sizeof(boolean) * (m + 1));
121     for(int i = 1; i <= m; i++){
122         readInteger(querya[i]);
123         readInteger(queryb[i]);
124         q.addDoubleEdge(querya[i], queryb[i], i);
125     }
126     dist[1] = 0;
127 }
128 
129 void tarjan(int node, int f){
130     uf[node] = node;
131     visited[node] = true;
132     for(int i = m_begin(g, node); i != 0; i = g[i].next){
133         int& e = g[i].end;
134         if(e == f)    continue;
135         dist[e] = dist[node] + g[i].w;
136         tarjan(e, node);
137         uf[e] = node;
138     }
139     for(int i = m_begin(q, node); i != 0; i = q[i].next) {
140         int& e = q[i].end;
141         if(visited[e] && enable[q[i].w]){
142             int lca = uf.find(e);
143             results[q[i].w] = lca;
144             enable[q[i].w] = false;
145         }
146     }
147 }
148 
149 inline void solve(){
150     tarjan(1, 0);
151     for(int i = 1; i <= m; i++){
152         int dis = dist[querya[i]] + dist[queryb[i]] - 2 * dist[results[i]];
153         printf("%d\n", dis);
154     }
155 }
156 
157 int main(){
158     freopen("distance.in", "r", stdin);
159     freopen("distance.out", "w", stdout);
160     init();
161     solve();
162     return 0;
163 }
distance (Tarjan)
  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 #ifndef    WIN32
 15 #define    AUTO "%I64d"
 16 #else
 17 #define AUTO "%lld"
 18 #endif
 19 using namespace std;
 20 typedef bool boolean;
 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 template<typename T>class Matrix{
 38     public:
 39         T *p;
 40         int lines;
 41         int rows;
 42         Matrix():p(NULL){    }
 43         Matrix(int rows, int lines):lines(lines), rows(rows){
 44             p = new T[(lines * rows)];
 45         }
 46         T* operator [](int pos){
 47             return (p + pos * lines);
 48         }
 49 };
 50 #define matset(m, i, s) memset((m).p, (i), (s) * (m).lines * (m).rows)
 51 
 52 ///map template starts
 53 typedef class Edge{
 54     public:
 55         int end;
 56         int next;
 57         int w;
 58         Edge(const int end = 0, const int next = 0, const int w = 0):end(end), next(next), w(w){}
 59 }Edge;
 60 typedef class MapManager{
 61     public:
 62         int ce;
 63         int *h;
 64         int w;
 65         Edge *edge;
 66         MapManager(){}
 67         MapManager(int points, int limit):ce(0){
 68             h = new int[(const int)(points + 1)];
 69             edge = new Edge[(const int)(limit + 1)];
 70             memset(h, 0, sizeof(int) * (points + 1));
 71         }
 72         inline void addEdge(int from, int end, int w){
 73             edge[++ce] = Edge(end, h[from], w);
 74             h[from] = ce;
 75         }
 76         inline void addDoubleEdge(int from, int end, int w){
 77             addEdge(from, end, w);
 78             addEdge(end, from, w);
 79         }
 80         Edge& operator[] (int pos) {
 81             return edge[pos];
 82         }
 83 }MapManager;
 84 #define m_begin(g, i) (g).h[(i)]
 85 ///map template ends
 86 
 87 int n, m;
 88 int cnt = 0;
 89 Matrix<int> st;
 90 int* seq;
 91 int* dep;
 92 int *app;
 93 MapManager g;
 94 int *mlog2;
 95 long long *dist;
 96 
 97 inline void init() {
 98     readInteger(n);
 99     g = MapManager(n, 2  * n);
100     seq = new int[(const int)(2 * n + 1)];
101     dist = new long long[(const int)(n + 1)];
102     dep = new int[(const int)(n + 1)];
103     app = new int[(const int)(n + 1)];
104     for(int i = 1, a, b, w; i < n; i++){
105         readInteger(a);
106         readInteger(b);
107         readInteger(w);
108         g.addDoubleEdge(a, b, w);
109     }
110     dist[1] = 0;
111     dep[0] = 0;
112 }
113 
114 void dfs(int node, int f) {
115     seq[++cnt] = node;
116     app[node] = cnt;
117     dep[node] = dep[f] + 1;
118     for(int i = m_begin(g, node); i != 0; i = g[i].next) {
119         int& e = g[i].end;
120         if(e == f)    continue;
121         dist[e] = dist[node] + g[i].w;
122         dfs(e, node);
123         seq[++cnt] = node;
124     }
125 }
126 
127 inline void init_log() {
128     mlog2 = new int[(const int)(2 * n + 1)];
129     mlog2[1] = 0;
130     for(int i = 2; i <= 2 * n; i++)
131         mlog2[i] = mlog2[i / 2] + 1; 
132 }
133 
134 inline void init_st() {
135     init_log();
136     st = Matrix<int>(cnt, mlog2[cnt] + 1);
137     for(int i = 1; i <= cnt; i++)
138         st[i][0] = seq[i];
139     for(int j = 1; j <= mlog2[cnt]; j++)
140         for(int i = 1; i + (1 << j) - 1 <= cnt; i++)
141             st[i][j] = (dep[st[i][j - 1]] < dep[st[i + (1 << (j - 1))][j - 1]]) ? (st[i][j - 1]) : (st[i + (1 << (j - 1))][j - 1]);
142 }
143 
144 inline int lca(int a, int b) {
145     if(app[a] > app[b])    swap(a, b);
146     int pos = mlog2[app[b] - app[a] + 1];
147     int u = st[app[a]][pos];
148     int v = st[app[b] - (1 << pos) + 1][pos];
149     return (dep[u] > dep[v]) ? (v) : (u);
150 }
151 
152 long long dis;
153 inline void solve() {
154     readInteger(m);
155     for(int i = 1, a, b; i <= m; i++){
156         readInteger(a);
157         readInteger(b);
158         int l = lca(a, b);
159         dis = dist[a] + dist[b] - 2 * dist[l];
160         printf(AUTO"\n", dis);
161     }
162 }
163 
164 int main() {
165     freopen("distance.in", "r", stdin);
166     freopen("distance.out", "w", stdout);
167     init();
168     dfs(1, 0);
169     init_st();
170     solve();
171     return 0;
172 }
distance (st table)

  话说ST表在n,q都尽量大的情况下,其他数据随机,竟然平均一个点比Tarjan 0.05s左右。(也有可能是我的st表写得比较丑)



  第二题还是一遍dfs序,接着可以开开心心地放线段树去装逼了。(然而我把某些"+="写成了"=",于是AK又没有了。。一定是写这道题和检查的时候头脑都不清醒)

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 #ifdef    WIN32
 15 #define    AUTO "%I64d"
 16 #else
 17 #define AUTO "%lld"
 18 #endif
 19 using namespace std;
 20 typedef bool boolean;
 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 Edge {
 38     public:
 39         int end;
 40         int next;
 41         Edge(const int end = 0, const int next = 0):end(end), next(next){        }
 42 }Edge;
 43 
 44 typedef class MapManager{
 45     public:
 46         int ce;
 47         Edge* edges;
 48         int* h;
 49         MapManager():ce(0), edges(NULL), h(NULL){        }
 50         MapManager(int points, int limit):ce(0){
 51             edges = new Edge[(const int)(limit + 1)];
 52             h = new int[(const int)(points + 1)];
 53             memset(h, 0, sizeof(int) * (points + 1));
 54         }
 55         inline void addEdge(int from, int end){
 56             edges[++ce] = Edge(end, h[from]);
 57             h[from] = ce;
 58         }
 59         inline void addDoubleEdge(int from, int end){
 60             addEdge(from, end);
 61             addEdge(end, from);
 62         }
 63         Edge& operator [](int pos){
 64             return edges[pos];
 65         }
 66 }MapManager;
 67 #define m_begin(g, i) (g).h[(i)]
 68 
 69 typedef class SegTreeNode{
 70     public:
 71         long long sum;
 72         int l, r;
 73         SegTreeNode *left, *right;
 74         long long lazy;
 75         SegTreeNode(int l, int r):l(l), r(r), sum(0), lazy(0), left(NULL), right(NULL){        }
 76         
 77         inline void pushUp(){
 78             this->sum = left->sum + right->sum;
 79         }
 80         
 81         inline void pushDown(){
 82             left->lazy += lazy;
 83             right->lazy += lazy;
 84             left->sum += lazy * (left->r - left->l + 1);
 85             right->sum += lazy * (right->r - right->l + 1);
 86             lazy = 0;
 87         }
 88 }SegTreeNode;
 89 
 90 typedef class SegTree {
 91     public:
 92         SegTreeNode* root;
 93         SegTree():root(NULL){    }
 94         SegTree(int size) {
 95             build(root, 1, size);
 96         }
 97         
 98         void build(SegTreeNode*& node, int l, int r){
 99             node = new SegTreeNode(l, r);
100             if(l == r)    return;
101             int mid = (l + r) >> 1;
102             build(node->left, l, mid);
103             build(node->right, mid + 1, r);
104         }
105         
106         void update(SegTreeNode*& node, int l, int r, int from, int end, long long val){
107             if(l == from && r == end){
108                 node->sum += val * (r - l + 1);
109                 node->lazy += val;
110                 return;
111             }
112             if(node->lazy)    node->pushDown();
113             int mid = (l + r) >> 1;
114             if(end <= mid)    update(node->left, l, mid, from, end, val);
115             else if(from > mid)    update(node->right, mid + 1, r, from, end, val);
116             else{
117                 update(node->left, l, mid, from, mid, val);
118                 update(node->right, mid + 1, r, mid + 1, end, val);
119             }
120             node->pushUp();
121         }
122         
123         long long query(SegTreeNode*& node, int index){
124             if(node->l == index && node->r == index){
125                 return node->sum;
126             }
127             if(node->lazy)    node->pushDown();
128             int mid = (node->l + node->r) >> 1;
129             if(index <= mid)    return query(node->left, index);
130             return query(node->right, index);
131         }
132         
133         long long query(SegTreeNode*& node, int from, int end){
134             if(node->l == from && node->r == end){
135                 return node->sum;
136             }
137             if(node->lazy)    node->pushDown();
138             int mid = (node->l + node->r) >> 1;
139             if(end <= mid)    return query(node->left, from, end);
140             if(from > mid)    return query(node->right, from, end);
141             return query(node->left, from, mid) + query(node->right, mid + 1, end);
142         }
143 }SegTree;
144 
145 int n, m;
146 SegTree st;
147 int cnt = 0;
148 int* visitID;
149 int* exitID;
150 MapManager g;
151 
152 inline void init() {
153     readInteger(n);
154     g = MapManager(n, 2 * n);
155     for(int i = 1, a, b; i < n; i++){
156         readInteger(a);
157         readInteger(b);
158         g.addDoubleEdge(a, b);
159     }
160     visitID = new int[(const int)(n + 1)];
161     exitID = new int[(const int)(n + 1)];
162 }
163 
164 void dfs(int node, int last){
165     visitID[node] = ++cnt;
166     for(int i = m_begin(g, node); i != 0; i = g[i].next) {
167         int& e = g[i].end;
168         if(e == last)    continue;
169         dfs(e, node);
170     }
171     exitID[node] = cnt;
172 }
173 
174 inline void solve() {
175     dfs(1, 0);
176     readInteger(m);
177     st = SegTree(n);
178     char cmd[10];
179     int a, b;
180     while(m--) {
181         scanf("%s", cmd);
182         readInteger(a);
183         if(cmd[0] == 'g') {
184             readInteger(b);
185             st.update(st.root, 1, n, visitID[a], exitID[a], b);
186         }else if(cmd[0] == 's'){
187             long long res = st.query(st.root, visitID[a]);
188             printf(AUTO"\n", res);
189         }else if(cmd[0] == 'a'){
190             long long res = st.query(st.root, visitID[a], exitID[a]);
191             printf(AUTO"\n", res);
192         }
193     }
194 }
195 
196 int main() {
197     freopen("redpacket.in", "r", stdin);
198     freopen("redpacket.out", "w", stdout);
199     init();
200     solve();
201     return 0;
202 }


 


  一看就发现是专为值域线段树设置的裸题。

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 #ifndef    WIN32
 15 #define    AUTO "%I64d"
 16 #else
 17 #define AUTO "%lld"
 18 #endif
 19 using namespace std;
 20 typedef bool boolean;
 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         int s;
 40         SegTreeNode* left, *right;
 41         
 42         inline void pushUp(){
 43             s = left->s + right->s;
 44         }
 45 }SegTreeNode;
 46 
 47 typedef class SegTree {
 48     public:
 49         int lb, rb;
 50         SegTreeNode* root;
 51         SegTree():root(NULL) {        }
 52         SegTree(int lb, int rb, int* list):lb(lb), rb(rb){
 53             build(root, 1, rb - lb + 1, list);
 54         }
 55         
 56         void build(SegTreeNode*& node, int l, int r, int* list){
 57             node = new SegTreeNode();
 58             if(l == r){
 59                 node->s = list[l];
 60                 return;
 61             }
 62             int mid = (l + r) >> 1;
 63             build(node->left, l, mid, list);
 64             build(node->right, mid + 1, r, list);
 65             node->pushUp();
 66         }
 67         
 68         void update(SegTreeNode*& node, int l, int r, int index, int val){
 69             if(l == index && r == index){
 70                 node->s += val;
 71                 smax(node->s, 0);
 72                 return;
 73             }
 74             int mid = (l + r) >> 1;
 75             if(index <= mid)    update(node->left, l, mid, index, val);
 76             else update(node->right, mid + 1, r, index, val);
 77             node->pushUp();
 78         }
 79         
 80         int findKth(SegTreeNode*& node, int l, int r, int k){
 81             if(l == r)    return l + lb - 1;
 82             int ls = node->left->s;
 83             int mid = (l + r) >> 1;
 84             if(k <= ls)    return findKth(node->left, l, mid, k);            
 85             return findKth(node->right, mid + 1, r, k - ls);
 86         }
 87 }SegTree;
 88 
 89 int n;
 90 int lb, rb;
 91 int* list;
 92 SegTree st;
 93 inline void init() {
 94     readInteger(lb);
 95     readInteger(rb);
 96     list = new int[(const int)(rb - lb + 2)];
 97     for(int i = lb; i <= rb; i++){
 98         readInteger(list[i - lb + 1]);
 99     }
100     st = SegTree(lb, rb, list);
101 }
102 
103 inline void solve() {
104     const int L = rb - lb + 1;
105     readInteger(n);
106     char cmd[10];
107     int a;
108     while(n--) {
109         scanf("%s", cmd);
110         readInteger(a);
111         if(cmd[0] == 'a'){
112             st.update(st.root, 1, L, a - lb + 1, 1);
113         }else if(cmd[0] == 'd'){
114             st.update(st.root, 1, L, a - lb + 1, -1);
115         }else{
116             int res = st.findKth(st.root, 1, L, a);
117             printf("%d\n", res);
118         }
119     }
120 }
121 
122 int main(){
123     freopen("kth.in", "r", stdin);
124     freopen("kth.out", "w", stdout);
125     init();
126     solve();
127     return 0;
128 }
值域线段树

  然后我还用了替罪羊树(然而发现,都快成普通的二叉搜索树了),O(n)离线建完整棵树,插入删除都不需要重构,即使为count为0也不管(删掉它需要花费更过的时间)。不过测了后发现,略微比值域线段树快一点,应该是因为各种操作在中途完成就开始返回了。

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 #ifndef    WIN32
 15 #define    AUTO "%I64d"
 16 #else
 17 #define AUTO "%lld"
 18 #endif
 19 using namespace std;
 20 typedef bool boolean;
 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 template<typename T>
 38 class ScapegoatTreeNode {
 39     public:
 40         T val;
 41         int count;
 42         int size;
 43         ScapegoatTreeNode* next[2];
 44         ScapegoatTreeNode():count(1), size(1){
 45             memset(next, 0, sizeof(next));
 46         }
 47         ScapegoatTreeNode(T val):val(val), count(1), size(1){
 48             memset(next, 0, sizeof(next));
 49         }
 50         
 51         inline void maintain() {
 52             size = count;
 53             for(int i = 0; i < 2; i++)
 54                 if(next[i] != NULL)
 55                     size += next[i]->size;
 56         }
 57         
 58         inline void addCount(int c){
 59             if(count == 0 && c < 0)    return;
 60             size += c, count += c;
 61         }
 62         
 63         inline int cmp(T x){
 64             if(val == x)    return -1;
 65             return (x < val) ? (0) : (1);
 66         }
 67 };
 68 
 69 template<typename T>
 70 class ScapegoatTree {
 71     protected:
 72         static void insert(ScapegoatTreeNode<T>*& node, T val){
 73             if(node == NULL){
 74                 node = new ScapegoatTreeNode<T>(val);
 75                 return;
 76             }
 77             int d = node->cmp(val);
 78             if(d == -1){
 79                 node->addCount(1);
 80                 return;
 81             }
 82             insert(node->next[d], val);
 83             node->maintain();
 84         }
 85         
 86         static boolean remove(ScapegoatTreeNode<T>*& node, T val){
 87             if(node == NULL)    return false;
 88             int d = node->cmp(val);
 89             if(d == -1){
 90                 node->addCount(-1);
 91                 return true;
 92             }
 93             boolean res = remove(node->next[d], val);
 94             if(res)    node->maintain();
 95             return res;
 96         }
 97         
 98         static ScapegoatTreeNode<T>* findKth(ScapegoatTreeNode<T>*& node, int k){
 99             int ls = (node->next[0] == NULL) ? (0) : (node->next[0]->size);
100             if(k >= ls + 1 && k <= ls + node->count)    return node;
101             if(k <= ls)    return findKth(node->next[0], k);
102             return findKth(node->next[1], k - ls - node->count);
103         }
104     public:
105         ScapegoatTreeNode<T>* root;
106         vector<ScapegoatTreeNode<T>*> lis;
107         
108         ScapegoatTree():root(NULL){        }
109         
110         ScapegoatTreeNode<T>* rebuild(int l, int r){
111             if(l > r)    return NULL;
112             int mid = (l + r) >> 1;
113             ScapegoatTreeNode<T>*& node = lis[mid];
114             node->next[0] = rebuild(l, mid - 1);
115             node->next[1] = rebuild(mid + 1, r);
116             node->maintain();
117             return node;
118         }
119         
120         void rebuild(ScapegoatTreeNode<T>*& node, ScapegoatTreeNode<T>*& f){
121             lis.clear();
122             travel(node);
123             int d = -1;
124             if(f != NULL)    d = f->cmp(node->val);
125             ScapegoatTreeNode<T>* res = rebuild(0, lis.size() - 1);
126             if(d != -1)        f->next[d] = res;
127             else root = res;
128         }
129         
130         void insert(T val){
131             insert(root, val);
132         }
133         
134         void remove(T val){
135             remove(root, val);
136         }
137         
138         ScapegoatTreeNode<T>* findKth(int k){
139             return findKth(root, k);
140         }
141 };
142 
143 int n;
144 int lb, rb;
145 ScapegoatTree<int> s;
146 
147 inline void init() {
148     readInteger(lb);
149     readInteger(rb);
150     for(int i = lb; i <= rb; i++){
151         ScapegoatTreeNode<int>* node = new ScapegoatTreeNode<int>(i);
152         readInteger(node->count);
153         node->maintain();
154         s.lis.push_back(node);
155     }
156     s.root = s.rebuild(0, s.lis.size() - 1);
157 }
158 
159 inline void solve() {
160     readInteger(n);
161     char cmd[10];
162     int a;
163     while(n--) {
164         scanf("%s", cmd);
165         readInteger(a);
166         if(cmd[0] == 'a'){
167             s.insert(a);
168         }else if(cmd[0] == 'd'){
169             s.remove(a);
170         }else{
171             ScapegoatTreeNode<int>* node = s.findKth(a);
172             printf("%d\n", node->val);
173         }
174     }
175 }
176 
177 int main(){
178     freopen("kth.in", "r", stdin);
179     freopen("kth.out", "w", stdout);
180     init();
181     solve();
182     return 0;
183 }
替罪羊树
posted @ 2017-01-22 21:57  阿波罗2003  阅读(197)  评论(1编辑  收藏  举报