Magic Ball Game 【HDU - 4605】

传送门

 

思路:对于每一个询问,我们都需要知道,从根节点出发,重量为X的球到达v点期间,往左走了几个点(比X大的几个,比X小的几个),往右走了几个点(比X大的几个,比X小的几个)。我们可以用dfs从根节点出发,先遍历左子树,再遍历右子树,对于遍历到的当前节点,我们查看是不是有到该点的询问,如果有,就需要"得到到达该点的路径中"往左走的点中几个点大于X,几个点小于X,往右也是同理,这里我们可以用线段树tree_l和tree_r来维护,这样我们只需要统计区间有几个点就行,该点询问之后我们把该点的信息加入到tree_l和tree_r中,注意需要回溯。当然还有中概率为0的情况,我们只需要标记路线中所有的权值,如果 X存在于路线中,则重量为X的球到达点v的概率就是0。

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <cstdio>
  4 #include <queue>
  5 
  6 using namespace std;
  7 
  8 #define lson(rt) (rt << 1)
  9 #define rson(rt) (rt << 1 | 1)
 10 
 11 const int N = 1e5 + 10;
 12 struct node
 13 {
 14     int rt, l, r, tot;
 15     inline int mid() { return (l + r) >> 1; }
 16     inline void init(int l1, int r1) { l = l1; r = r1; tot = 0; }
 17 }tree[2][N << 2];
 18 vector<int > Rank;
 19 vector<int > to[N];
 20 vector<pair<int ,int > > hav[N];
 21 int ans[N][2];
 22 int v[N], app[N];
 23 int Max;
 24 
 25 void Build(int rt, int l, int r)
 26 {
 27     tree[0][rt].init(l, r);
 28     tree[1][rt].init(l, r);
 29     if(l == r) return;
 30     Build(lson(rt), l, tree[0][rt].mid());
 31     Build(rson(rt), tree[0][rt].mid() + 1, r);
 32 }
 33 
 34 int Query(int rt, int l, int r, int d1, int d2, int pos)
 35 {
 36     if(d1 > d2) return 0;
 37     if(d1 <= l && r <= d2) return tree[pos][rt].tot;
 38 
 39     if(tree[pos][rt].mid() >= d2) {
 40         return Query(lson(rt), l, tree[pos][rt].mid(), d1, d2, pos);
 41     } else if(tree[pos][rt].mid() < d1) {
 42         return Query(rson(rt), tree[pos][rt].mid() + 1, r, d1, d2, pos);
 43     } else {
 44         return Query(lson(rt), l, tree[pos][rt].mid(), d1, d2, pos) +
 45                 Query(rson(rt), tree[pos][rt].mid() + 1, r, d1, d2, pos);
 46     }
 47 }
 48 
 49 inline void Push_up(int rt, int pos)
 50 {
 51     tree[pos][rt].tot = tree[pos][lson(rt)].tot + tree[pos][rson(rt)].tot;
 52 }
 53 
 54 void Add(int rt, int l, int r, int id, int v, int pos)
 55 {
 56     if(l == r) {
 57         tree[pos][rt].tot += v;
 58         return ;
 59     }
 60 
 61     if(tree[pos][rt].mid() >= id) {
 62         Add(lson(rt), l, tree[pos][rt].mid(), id, v, pos);
 63     } else {
 64         Add(rson(rt), tree[pos][rt].mid() + 1, r, id, v, pos);
 65     }
 66 
 67     Push_up(rt, pos);
 68 }
 69 
 70 void dfs(int now)
 71 {
 72     for(auto info : hav[now]) {
 73         int id_ball = lower_bound(Rank.begin(), Rank.end(), info.second) - Rank.begin() + 1;
 74         //printf("v[%d] = %d app = %d info.second = %d\n", now, v[now], app[id_ball], info.second);
 75         if(app[id_ball] && info.second == Rank[id_ball - 1]) {
 76             ans[info.first][0] = -1;
 77          //   cout << "76 lines" << endl;
 78         } else {
 79             int Max_l = Query(1, 1, Max, 1, id_ball - 1, 0);
 80             int Max_r = Query(1, 1, Max, 1, id_ball - 1, 1);
 81             int Min_l = Query(1, 1, Max, id_ball, Max, 0);
 82             int Min_r = Query(1, 1, Max, id_ball, Max, 1);
 83            // printf("Min_l = %d Min_r =  %d Max_l = %d Max_r = %d\n", Min_l, Min_r, Max_l, Max_r);
 84             ans[info.first][0] = Max_r;
 85             ans[info.first][1] = Min_l + Min_r + 3 * (Max_l + Max_r);
 86         }
 87     }
 88 
 89     if(!to[now].size()) return;
 90 
 91     int id = lower_bound(Rank.begin(), Rank.end(), v[now]) - Rank.begin() + 1;
 92     app[id]++;
 93     Add(1, 1, Max, id, 1, 0);
 94     dfs(to[now][0]);
 95     app[id]--;
 96     Add(1, 1, Max, id, -1, 0);
 97 
 98     id = lower_bound(Rank.begin(), Rank.end(), v[now]) - Rank.begin() + 1;
 99     app[id]++;
100     Add(1, 1, Max, id, 1, 1);
101     dfs(to[now][1]);
102     app[id]--;
103     Add(1, 1, Max, id, -1, 1);
104 }
105 
106 void work()
107 {
108     Build(1, 1, Max);
109 
110     dfs(1);
111 }
112 
113 void init(int n)
114 {
115     Rank.clear();
116     for(int i = 1; i <= n; ++i) {
117         to[i].clear();
118         hav[i].clear();
119         app[i] = 0;
120     }
121 }
122 
123 void solve()
124 {
125     int T;
126     scanf("%d", &T);
127     while(T--) {
128 
129         int n;
130         scanf("%d", &n);
131 
132         init(n);
133 
134         ///价值
135         for(int i = 1; i <= n; ++i) {
136             scanf("%d", v + i);
137            // Max = max(Max, v[i]);
138             Rank.push_back(v[i]);
139         }
140 
141         ///
142         int m;
143         scanf("%d", &m);
144         for(int i = 1; i <= m; ++i) {
145             int x, y1, y2;
146             scanf("%d%d%d", &x, &y1, &y2);
147             to[x].push_back(y1);
148             to[x].push_back(y2);
149         }
150 
151 
152         ///询问
153         int q;
154         scanf("%d", &q);
155         for(int i = 1; i <= q; ++i) {
156             int x, y;
157             scanf("%d%d", &x, &y);
158             hav[x].push_back(make_pair(i, y));
159         }
160 
161         sort(Rank.begin(), Rank.end());
162         Rank.erase(unique(Rank.begin(), Rank.end()), Rank.end());
163         Max = Rank.size();
164 
165         work();
166 
167         for(int i = 1; i <= q; ++i) {
168             if(ans[i][0] == -1) printf("0\n");
169             else printf("%d %d\n", ans[i][0], ans[i][1]);
170         }
171 
172     }
173 }
174 
175 int main()
176 {
177     solve();
178 
179     return 0;
180 }
181 
182 /*
183 99
184 3
185 2 3 1
186 1
187 1 2 3
188 3
189 3 2
190 1 1
191 3 4
192 
193 5
194 2 3 1 3 1
195 2
196 1 2 3
197 3 4 5
198 5
199 3 2
200 1 1
201 3 4
202 4 3
203 5 3
204 
205 5
206 2 3 5 3 1
207 2
208 1 2 3
209 3 4 5
210 5
211 3 2
212 1 1
213 3 4
214 4 6
215 5 3
216 */

 

posted @ 2020-11-21 19:32  SummerMingQAQ  阅读(171)  评论(0编辑  收藏  举报