POJ 3764
题意:略
思路:
利用Trie来处理N个数的两两异或最大值;
Code:
//#include<bits/stdc++.h>
//using namespace std;
//typedef long long LL;
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
struct Edge{
int v, w, ne;
Edge(){};
Edge(int v, int w, int ne) : v(v), w(w), ne(ne) {}
};
Edge edge[200007];
int head[100007], tol;
int n, d[100007];
int tr[3000007][2];
struct Run{
int tmp[33], cnt, ans;
int Creat(){
tr[cnt][0] = tr[cnt][1] = -1;
return cnt++;
}
void Find(int x){
int now = 0, w = 0;
for(int i=30;i>=0;i--){
if(tr[now][1-tmp[i]] != -1) now = tr[now][1-tmp[i]], w |= (1<<i);
else now = tr[now][tmp[i]];
}
ans = max(ans, w);
}
void ok_tmp(int x){
memset(tmp, 0, sizeof(tmp));
int num = 0;
while(x){
tmp[num++] = x & 1;
x >>= 1;
}
}
void ins(int x){
ok_tmp(x);
int now = 0, m;
for(int i=30;i>=0;i--){
m = tmp[i];
if(tr[now][m] == -1)
tr[now][m] = Creat();
now = tr[now][m];
}
}
void DFS(int u, int fa){
int v;
for(int i=head[u];~i;i=edge[i].ne){
v = edge[i].v;
if(v == fa) continue;
d[v] = d[u] ^ edge[i].w;
DFS(v, u);
}
}
void solve(){
cnt = 0;
fill(head, head+n, -1);
tol = 0;
int u, v, w;
for(int i=1;i<n;i++){
scanf("%d%d%d", &u, &v, &w);
edge[tol] = Edge(v, w, head[u]), head[u] = tol++;
edge[tol] = Edge(u, w, head[v]), head[v] = tol++;
}
d[0] = 0;
DFS(0, -1);
ans = 0;
Creat();
for(int i=0;i<n;i++){
ins(d[i]);
Find(d[i]);
}
printf("%d\n", ans);
}
};
int main(){
while(~scanf("%d", &n)){
Run cc = Run();
cc.solve();
}
return 0;
}
Codeforces 842D
题意:略
思路:
求当前不存在异或值的最小值;
利用Trie来处理N个数与一个数的异或最小值;
Code:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int eix[524290];
int n, q;
int tr[6000007][2];
struct Run{
int tmp[23], cnt;
int Creat(){
tr[cnt][0] = tr[cnt][1] = -1;
return cnt++;
}
int Find(){
int now = 0, w = 0;
for(int i=21;i>=0;i--){
if(tr[now][tmp[i]] != -1) now = tr[now][tmp[i]];
else now = tr[now][1-tmp[i]], w |= (1<<i);
}
return w;
}
void ok_tmp(int x){
memset(tmp, 0, sizeof(tmp));
int num = 0;
while(x){
tmp[num++] = x & 1;
x >>= 1;
}
}
void ins(int x){
ok_tmp(x);
int now = 0, m;
for(int i=21;i>=0;i--){
m = tmp[i];
if(tr[now][m] == -1)
tr[now][m] = Creat();
now = tr[now][m];
}
}
void solve(){
int x;
scanf("%d%d", &n, &q);
for(int i=1;i<=n;i++){
scanf("%d", &x);
eix[x] = 1;
}
Creat();
for(int i=0;i<=524288;i++)
if(!eix[i]) ins(i);
int now = 0;
Creat();
for(int i=0;i<q;i++){
scanf("%d", &x);
now ^= x;
ok_tmp(now);
printf("%d\n", Find());
}
}
};
int main(){
Run cc = Run();
cc.solve();
return 0;
}
Codeforces 842C
题意:略
思路:
对于树上每个位置置0或不置。
a[ u ]置0,那就是root->father[ u ]上的gcd值;
a[ u ]不置0,那就是维护每个位置的所有情况的gcd(复杂度log系列)
Code:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int a[200007];
vector<int>edge[200007], dp[200007];
int n;
struct Run{
void DFS(int u, int pre, int fa){
int v;
sort(dp[u].begin(), dp[u].end());
dp[u].erase(unique(dp[u].begin(), dp[u].end()), dp[u].end());
unsigned sz = dp[u].size(), esz = edge[u].size();
for(unsigned i=0; i<esz; i++){
v = edge[u][i];
if(fa == v) continue;
dp[v].push_back(pre); //0
for(unsigned j=0;j<sz;j++){
int x = __gcd(a[v], dp[u][j]);
dp[v].push_back(x);
}
DFS(v, __gcd(pre, a[v]), u);
}
}
void solve(){
int u, v;
scanf("%d", &n);
for(int i=1;i<=n;i++){
scanf("%d", &a[i]);
}
for(int i=1;i<n;i++){
scanf("%d%d", &u, &v);
edge[u].push_back(v);
edge[v].push_back(u);
}
dp[1].push_back(a[1]);
dp[1].push_back(0);
DFS(1, a[1], -1);
for(int i=1;i<=n;i++)
printf("%d ", dp[i].back());
}
};
int main(){
Run cc = Run();
cc.solve();
return 0;
}