博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【LOJ】 #2013. 「SCOI2016」幸运数字
阅读量:4973 次
发布时间:2019-06-12

本文共 3686 字,大约阅读时间需要 12 分钟。

题解

最大异或和,明显是个线性基

然而还有那么多路径……那就树分治,反正点数看起来很少,就是为了让人乘上一个60的常数嘛
把一个树的点分树记录下来,然后看看询问的两个点彼此相同的最后一个父亲是谁,把这个询问挂在这个点上,计算就暴力搜索这棵树里每一个节点到重心的线性基就行了,最后再用60的常数把两个线性基合起来

代码

#include 
//#define ivorysi#define MAXN 20005#define MAXQ 200005typedef long long int64;typedef unsigned int u32;using namespace std;struct node { int to,next;}edge[MAXN * 2];int head[MAXN],sumE,n,m;int64 val[MAXN];vector
aux[MAXN],qry[MAXN];bool vis[MAXN];int que[MAXN],qr,ql;int siz[MAXN],son[MAXN],fa[MAXN];int st[MAXQ],ed[MAXQ];int64 dp[MAXN][65],ans[MAXQ];void add(int u,int v) { edge[++sumE].to = v; edge[sumE].next = head[u]; head[u] = sumE;}void addtwo(int u,int v) { add(u,v);add(v,u);}int calc_G(int u) { que[ql = qr = 1] = u; fa[u] = 0; while(ql <= qr) { int now = que[ql++]; siz[now] = 1;son[now] = 0; for(int i = head[now] ; i ; i = edge[i].next) { int v = edge[i].to; if(!vis[v] && fa[now] != v) { que[++qr] = v; fa[v] = now; } } } int res = que[qr]; for(int i = qr ; i >= 1 ; --i) { int now = que[i]; siz[fa[now]] += siz[now]; if(siz[now] > son[fa[now]]) son[fa[now]] = siz[now]; if(qr - siz[now] > son[now]) son[now] = qr - siz[now]; if(son[now] < son[res]) res = now; } return res;}void dfs(int u) { int G = calc_G(u); vis[G] = 1; for(int i = 1 ; i <= qr ; ++i) aux[que[i]].push_back(G); for(int i = head[G] ; i ; i = edge[i].next) { int v = edge[i].to; if(!vis[v]) dfs(v); }}void Init() { scanf("%d%d",&n,&m); for(int i = 1 ; i <= n ; ++i) scanf("%lld",&val[i]); int u,v; for(int i = 1 ; i < n ; ++i) { scanf("%d%d",&u,&v); addtwo(u,v); } dfs(1); for(int i = 1 ; i <= m ; ++i) { scanf("%d%d",&st[i],&ed[i]); if(st[i] == ed[i]) ans[i] = val[st[i]]; } for(int i = 1 ; i <= m ; ++i) { if(st[i] == ed[i]) continue; int s = min(aux[st[i]].size(),aux[ed[i]].size()); bool flag = false; for(int j = 0 ; j < s ; ++j) { if(aux[st[i]][j] != aux[ed[i]][j]) { qry[aux[st[i]][j - 1]].push_back(i); flag = 1; break; } } if(!flag) qry[aux[st[i]][s - 1]].push_back(i); }}void insert(int id,int64 v) { for(int j = 60 ; j >= 0 ; --j) { if(v >> j & 1) { if(dp[id][j]) v ^= dp[id][j]; else { dp[id][j] = v; for(int k = 60 ; k > j ; --k) { if(dp[id][k] >> j & 1) dp[id][k] ^= dp[id][j]; } break; } } }}void calc(int u) { que[ql = qr = 1] = u; fa[u] = 0; memset(dp[u],0,sizeof(dp[u])); while(ql <= qr) { int now = que[ql++]; for(int i = head[now] ; i ; i = edge[i].next) { int v = edge[i].to; if(!vis[v] && fa[now] != v) { fa[v] = now; memcpy(dp[v],dp[now],sizeof(dp[now])); insert(v,val[v]); que[++qr] = v; } } }}void Process(int u) { for(auto k : aux[u]) vis[u] = 1; calc(u); for(auto k : qry[u]) { memset(dp[n + 1],0,sizeof(dp[n + 1])); insert(n + 1,val[u]); for(int i = 0 ; i <= 60 ; ++i) { if(dp[st[k]][i]) insert(n + 1,dp[st[k]][i]); if(dp[ed[k]][i]) insert(n + 1,dp[ed[k]][i]); } for(int i = 60 ; i >= 0 ; --i) { if(!dp[n + 1][i]) continue; if(!(ans[k] >> i & 1)) ans[k] ^= dp[n + 1][i]; } } for(auto k : aux[u]) vis[u] = 0;}void Solve() { memset(vis,0,sizeof(vis)); for(int i = 1 ; i <= n ; ++i) { if(qry[i].size() != 0) { Process(i); } } for(int i = 1 ; i <= m ; ++i) { printf("%lld\n",ans[i]); }}int main() {#ifdef ivorysi freopen("f1.in","r",stdin);#endif Init(); Solve();}

转载于:https://www.cnblogs.com/ivorysi/p/9155841.html

你可能感兴趣的文章
[Git] 005 初识 Git 与 GitHub 之分支
查看>>
使用Analyze 和Instruments-Leaks分析解决iOS内存泄露
查看>>
Vue.js的入门
查看>>
【自定义异常】
查看>>
pip install 后 importError no module named "*"
查看>>
一些疑惑
查看>>
Codeforces Round #413 A. Carrot Cakes
查看>>
Linux(Ubuntu16.04)下添加新用户
查看>>
Windows c++应用程序通用日志组件(组件及测试程序下载)
查看>>
openstack dpdk
查看>>
【BZOJ2333】【SCOI2011】棘手的操作 treap合并
查看>>
【BZOJ1013】【JSOI2008】球形空间产生器 高斯消元
查看>>
java泛型
查看>>
基本配置2-被忽悠进了CentOS 6
查看>>
MFC的组合框(ComboBox)控件切换下拉样式
查看>>
WPF 中依赖属性的继承(Inherits)
查看>>
HttpPost works in Java project, not in Android
查看>>
JavaScript摘要
查看>>
nginx与fastdfs配置详解与坑
查看>>
tf.nn.embedding_lookup TensorFlow embedding_lookup 函数最简单实例
查看>>