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 }