HDU--5589(莫队,字典树)

2015-12-07 22:07:37

传送门

题意:一棵树有N个节点,编号为1到N,每条边都有边权。定义f(u,v)为从u到v路径上所有边权的异或和。给定一个数M,有Q次查询,每次给定一个区间[l,r],询问有多少对(u,v)满足f(u,v)>M (l <=u<v<= r),数据范围:5w

思路:考虑离线莫队,先处理处F[i]表示从根1到点i的路径的xor和。对于更改,等价于处理从一个点出发到若干个点的路径xor和大于M的个数。可以用字典树存下当前存在的所有路径xor和,当查询时,如果要>M,必然是二进制下某一位,xor和为1,M为0,且比该位高的数位都相同。那么就可以在字典树上记录一下子树大小sz,然后枚举不同的那一位。

  1 #include <cstdio>
  2 #include <ctime>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <cmath>
  6 #include <vector>
  7 #include <map>
  8 #include <set>
  9 #include <stack>
 10 #include <queue>
 11 #include <string>
 12 #include <iostream>
 13 #include <algorithm>
 14 using namespace std;
 15 
 16 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
 17 #define MEM(a,b) memset(a,b,sizeof(a))
 18 #define MP(a,b) make_pair(a,b)
 19 #define PB push_back
 20 
 21 typedef long long ll;
 22 typedef pair<int,int> pii;
 23 const double eps = 1e-8;
 24 const int INF = (1 << 30) - 1;
 25 const int MAXN = 100010;
 26 
 27 int N,M,Q;
 28 int block,tot;
 29 int first[MAXN],ecnt;
 30 int F[MAXN];
 31 int Ms[30];
 32 ll ans;
 33 
 34 struct edge{
 35     int v,next,c;
 36 }e[MAXN << 1];
 37 
 38 struct Node{
 39     int x,y,id,bid;
 40     ll ans;
 41 }q[MAXN];
 42 
 43 struct Trie{
 44     int nxt[2];
 45     int sz;
 46 }t[MAXN * 30];
 47 
 48 bool cmp(Node a,Node b){
 49     return a.bid == b.bid ? a.y < b.y : a.bid < b.bid;
 50 }
 51 
 52 bool cmp_id(Node a,Node b){
 53     return a.id < b.id;
 54 }
 55 
 56 inline void Clear(int p){
 57     t[p].nxt[0] = t[p].nxt[1] = 0;
 58     t[p].sz = 0;
 59 }
 60 
 61 void Dfs(int p,int pre,int cur){
 62     F[p] = cur;
 63     for(int i = first[p]; ~i; i = e[i].next){
 64         int v = e[i].v;
 65         if(v == pre) continue;
 66         Dfs(v,p,cur ^ e[i].c);
 67     }
 68 }
 69 
 70 void Insert_tree(int v){
 71     int s[30] = {0},sz = 0;
 72     int p = 0;
 73     while(v){
 74         s[++sz] = v & 1;
 75         v >>= 1;
 76     }
 77     for(int i = 20; i >= 1; --i){
 78         int id = s[i];
 79         if(t[p].nxt[id] == 0){
 80             t[p].nxt[id] = ++tot;
 81             Clear(tot);
 82         }
 83         p = t[p].nxt[id];
 84         t[p].sz++;
 85     }
 86 }
 87 
 88 void Delete_tree(int v){
 89     int s[30] = {0},sz = 0;
 90     int p = 0;
 91     while(v){
 92         s[++sz] = v & 1;
 93         v >>= 1;
 94     }
 95     for(int i = 20; i >= 1; --i){
 96         int id = s[i];
 97         if(t[p].nxt[id] == 0){
 98             t[p].nxt[id] = ++tot;
 99             Clear(tot);
100         }
101         p = t[p].nxt[id];
102         t[p].sz--;
103     }
104 }
105 
106 ll Query_tree(int v){
107     int s[30] = {0},sz = 0;
108     int p = 0;
109     ll res = 0;
110     while(v){
111         s[++sz] = v & 1;
112         v >>= 1;
113     }
114     for(int i = 20; i >= 1; --i){
115         int id = s[i];
116         int a_id = id ^ 1;
117         if(Ms[i] == 1){
118             if(t[p].nxt[a_id] == 0 || t[t[p].nxt[a_id]].sz == 0) break;
119             p = t[p].nxt[a_id];
120         }
121         else{
122             if(t[p].nxt[a_id]) res += t[t[p].nxt[a_id]].sz;
123             if(t[p].nxt[id] == 0 || t[t[p].nxt[id]].sz == 0) break;
124             p = t[p].nxt[id];
125         }
126     }
127     return res;
128 }
129 
130 inline void add_edge(int u,int v,int c){
131     e[ecnt].next = first[u];
132     e[ecnt].v = v;
133     e[ecnt].c = c;
134     first[u] = ecnt++;
135 }
136 
137 void Update(int l,int r,int f){
138     for(int i = l; i <= r; ++i){
139         ll v = Query_tree(F[i]);
140         //printf("%d , F : %d , %cv : %lld\n",i,F[i],f == 1 ? '+' : '-',v);
141         if(f == 1) ans += v,Insert_tree(F[i]);
142         else ans -= v,Delete_tree(F[i]);
143     }
144 }
145 
146 void Block(){
147     ans = 0;
148     sort(q + 1,q + Q + 1,cmp);
149     for(int i = 1,l = 1,r = 0; i <= Q; ++i){
150         //printf("[ %d , %d ] --> [ %d , %d ] \n",l,r,q[i].x,q[i]);
151         if(l < q[i].x) Update(l,q[i].x - 1,-1);
152         if(q[i].x < l) Update(q[i].x,l - 1,1);
153         if(r < q[i].y) Update(r + 1,q[i].y,1);
154         if(q[i].y < r) Update(q[i].y + 1,r,-1);
155         q[i].ans = ans;
156         l = q[i].x,r = q[i].y;
157     }
158     sort(q + 1,q + Q + 1,cmp_id);
159     for(int i = 1; i <= Q; ++i){
160         printf("%lld\n",q[i].ans);
161     }
162 }
163 
164 int main(){
165     while(scanf("%d%d%d",&N,&M,&Q) != EOF){
166         memset(Ms,0,sizeof(Ms));
167         memset(first,-1,sizeof(first));
168         ecnt = tot = 0;
169         Clear(0);
170         block = 300;
171         int sz = 0;
172         while(M){
173             Ms[++sz] = M & 1;
174             M >>= 1;
175         }
176         for(int i = 1; i < N; ++i){
177             int a,b,c;
178             scanf("%d%d%d",&a,&b,&c);
179             add_edge(a,b,c);
180             add_edge(b,a,c);
181         }
182         Dfs(1,-1,0);
183         for(int i = 1; i <= Q; ++i){
184             scanf("%d%d",&q[i].x,&q[i].y);
185             q[i].id = i;
186             q[i].bid = q[i].x / block;
187         }
188         Block();
189     }
190     return 0;
191 }

 

posted @ 2015-12-07 22:15  Naturain  阅读(234)  评论(0编辑  收藏  举报