bzoj 4568: [Scoi2016]幸运数字
4568: [Scoi2016]幸运数字
Time Limit: 60 Sec Memory Limit: 256 MB
Submit: 848 Solved: 336
[Submit][Status][Discuss]
Description

然后发现果然合并有更NB的方法。
不是高斯消元(原谅我zz),而是应该一个一个插。
终于19sA掉了。
52s
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
#define N 20005
using namespace std;
int read()
{
int p=;char c=getchar();
while(c<''||c>'')c=getchar();
while(c>=''&&c<='')p=p*+c-'',c=getchar();
return p;
}
int n,m;
int head[N],ver[N*],nxt[N*],tot;
ll mi[N];
void add(int a,int b)
{
tot++;nxt[tot]=head[a];head[a]=tot;ver[tot]=b;return ;
}
ll ji[N][][];
int fa[N][],dep[N];
ll a[N];
void dfs(int x,int f)
{
for(int i=head[x];i;i=nxt[i])
{
if(ver[i]==f)continue;
fa[ver[i]][]=x;
dep[ver[i]]=dep[x]+;
ji[ver[i]][][]=;
ji[ver[i]][][]=a[ver[i]];
dfs(ver[i],x);
}
return ;
}
ll tmp[];
void guess()
{
int k=;int now=tmp[];
for(int i=;i>=;i--)
{
int p=;ll o=mi[i];
for(int j=k;j<=now;j++)
{
if((tmp[j]&o))
{
p=j;break;
}
}
if(p)
{
swap(tmp[p],tmp[k]);
for(int j=;j<=now;j++)
{
if(j!=k&&(tmp[j]&o))
{
tmp[j]^=tmp[k];
}
}k++;
}
}
tmp[]=k-;
}
void yu()
{
for(int i=;i<=;i++)
{
for(int j=;j<=n;j++)
{
tmp[]=ji[j][i-][]+ji[fa[j][i-]][i-][];
for(int k=;k<=ji[j][i-][];k++)tmp[k]=ji[j][i-][k];
for(int k=;k<=ji[fa[j][i-]][i-][];k++)tmp[k+ji[j][i-][]]=ji[fa[j][i-]][i-][k];
guess();
for(int k=;k<=tmp[];k++)ji[j][i][k]=tmp[k];
fa[j][i]=fa[fa[j][i-]][i-];
}
}return ;
}
void solve(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
for(int i=;i>=;i--)
{
if(dep[fa[x][i]]>=dep[y])
{
for(int j=;j<=ji[x][i][];j++)tmp[]++,tmp[tmp[]]=ji[x][i][j];
guess();
x=fa[x][i];
}
}
if(x!=y)
{
for(int i=;i>=;i--)
{
if(fa[x][i]!=fa[y][i])
{
for(int k=;k<=ji[x][i][];k++)tmp[]++,tmp[tmp[]]=ji[x][i][k];
guess();
for(int k=;k<=ji[y][i][];k++)tmp[]++,tmp[tmp[]]=ji[y][i][k];
guess();
x=fa[x][i];y=fa[y][i];
}
}
tmp[]++;tmp[tmp[]]=a[fa[x][]];
tmp[]++;tmp[tmp[]]=a[x];
tmp[]++;tmp[tmp[]]=a[y];
}
else
{
tmp[]++,tmp[tmp[]]=a[x];
}
guess();
ll now=;
for(int i=tmp[];i>=;i--)
{
now^=tmp[i];
}
printf("%lld\n",now);
return ;
}
int main()
{
int q;
mi[]=;
for(int i=;i<=;i++)mi[i]=mi[i-]*;
scanf("%d%d",&n,&q);
for(int i=;i<=n;i++)
{
scanf("%lld",&a[i]);
}
int t1,t2,t3;
for(int i=;i<n;i++)
{
t1=read();t2=read();
add(t1,t2);add(t2,t1);
}
dep[]=;
ji[][][]=;ji[][][]=a[];
dfs(,-);
yu();
for(int i=;i<=q;i++)
{
t1=read();t2=read();
memset(tmp,,sizeof(tmp));
solve(t1,t2);
}
return ;
}
19s
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
#define N 20005
using namespace std;
int read()
{
int p=;char c=getchar();
while(c<''||c>'')c=getchar();
while(c>=''&&c<='')p=p*+c-'',c=getchar();
return p;
}
int n,m;
int head[N],ver[N*],nxt[N*],tot;
ll mi[N];
void add(int a,int b)
{
tot++;nxt[tot]=head[a];head[a]=tot;ver[tot]=b;return ;
}
ll ji[N][][];
int fa[N][],dep[N];
ll a[N];
void dfs(int x,int f)
{
for(int i=head[x];i;i=nxt[i])
{
if(ver[i]==f)continue;
fa[ver[i]][]=x;
dep[ver[i]]=dep[x]+;
for(int j=;j>=;j--)
{
if(a[ver[i]]&mi[j])
{
ji[ver[i]][][j]=a[ver[i]];
break;
}
}
dfs(ver[i],x);
}
return ;
}
ll tmp[];
void insert(ll x)
{
for(int i=;i>=;i--)
{
if(x&mi[i])
{
if(!tmp[i])
{
tmp[i]=x;
break;
}
else x^=tmp[i];
}
}return ;
}
void yu()
{
for(int i=;i<=;i++)
{
for(int j=;j<=n;j++)
{
for(int k=;k<=;k++)tmp[k]=ji[j][i-][k];
for(int k=;k<=;k++)
{
if(ji[fa[j][i-]][i-][k])insert(ji[fa[j][i-]][i-][k]);
}
for(int k=;k<=;k++)ji[j][i][k]=tmp[k];
fa[j][i]=fa[fa[j][i-]][i-];
}
}return ;
}
void solve(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
for(int i=;i>=;i--)
{
if(dep[fa[x][i]]>=dep[y])
{
for(int j=;j<=;j++)if(ji[x][i][j])insert(ji[x][i][j]);
x=fa[x][i];
}
}
if(x!=y)
{
for(int i=;i>=;i--)
{
if(fa[x][i]!=fa[y][i])
{
for(int k=;k<=;k++)if(ji[x][i][k])insert(ji[x][i][k]);
for(int k=;k<=;k++)if(ji[y][i][k])insert(ji[y][i][k]);
x=fa[x][i];y=fa[y][i];
}
}
insert(a[fa[x][]]);insert(a[x]);insert(a[y]);
}
else
{
insert(a[x]);
}
ll now=;
for(int i=;i>=;i--)
{
now=max(now,now^(tmp[i]));
}
printf("%lld\n",now);
return ;
}
int main()
{
int q;
mi[]=;
for(int i=;i<=;i++)mi[i]=mi[i-]*;
scanf("%d%d",&n,&q);
for(int i=;i<=n;i++)
{
scanf("%lld",&a[i]);
}
int t1,t2,t3;
for(int i=;i<n;i++)
{
t1=read();t2=read();
add(t1,t2);add(t2,t1);
}
dep[]=;
for(int i=;i>=;i--)
{
if(a[]&mi[i])
{
ji[][][i]=a[];
break;
}
}
dfs(,-);
yu();
for(int i=;i<=q;i++)
{
t1=read();t2=read();
memset(tmp,,sizeof(tmp));
solve(t1,t2);
}
return ;
}
bzoj 4568: [Scoi2016]幸运数字的更多相关文章
- BZOJ 4568: [Scoi2016]幸运数字 [线性基 倍增]
4568: [Scoi2016]幸运数字 题意:一颗带点权的树,求树上两点间异或值最大子集的异或值 显然要用线性基 可以用倍增的思想,维护每个点向上\(2^j\)个祖先这些点的线性基,求lca的时候合 ...
- BZOJ 4568 [Scoi2016]幸运数字(树链剖分 + 异或线性基)
题目链接 BZOJ 4568 考虑树链剖分+线段树维护每一段区域的异或线性基 对于每个询问,求出该点集的异或线性基.然后求一下这个线性基里面能异或出的最大值即可. #include <bits ...
- bzoj 4568: [Scoi2016]幸运数字【树链剖分+线段树+线性基】
一眼做法,好处是好想好写坏处是常数大,容易被卡(bzoj loj 洛谷开O2 能AC,不开有90分-- 大概就是树剖之后维护线段树,在线段树的每个节点上上维护一个线性基,暴力\( 60^2 \)的合并 ...
- BZOJ 4568 [Scoi2016]幸运数字 ——线性基 倍增
[题目分析] 考虑异或的最大值,维护线性基就可以了. 但是有多次的询问,树剖或者倍增都可以. 想了想树剖动辄数百行的代码. 算了,我还是写倍增吧. 注:被位运算和大于号的优先级坑了一次,QaQ [代码 ...
- BZOJ 4568: [Scoi2016]幸运数字(倍增+线性基)
传送门 解题思路 异或最大值肯定线性基了,树上两点那么就倍增搞一搞,就维护每个点到各级祖先的线性基,时间复杂度\(O(nlog^3n)\),并不知道咋过去的. 代码 #include<iostr ...
- 【BZOJ 4568】 4568: [Scoi2016]幸运数字 (线性基+树链剖分+线段树)
4568: [Scoi2016]幸运数字 Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个 幸运数字,以纪念碑的形 ...
- BZOJ.4516.[SCOI2016]幸运数字(线性基 点分治)
题目链接 线性基可以\(O(log^2)\)暴力合并.又是树上路径问题,考虑点分治. 对于每个点i求解 LCA(u,v)==i 时的询问(u,v),只需求出这个点到其它点的线性基后,暴力合并. LCA ...
- [BZOJ4568][Scoi2016]幸运数字 倍增+线性基
4568: [Scoi2016]幸运数字 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 1791 Solved: 685[Submit][Statu ...
- [BZOJ4568][SCOI2016]幸运数字(倍增LCA,点分治+线性基)
4568: [Scoi2016]幸运数字 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 2131 Solved: 865[Submit][Statu ...
随机推荐
- Azure web site和web job的config文件加密方式
1.分析 由于Azure Web AppService平台的特殊性,所以在C#中原先的config加密方法DataProtectionConfigurationProvider和RSAProtecte ...
- truffle Dapp 搭建
安装truffle $ npm install -g truffle 依赖环境 NodeJS 访问https://nodejs.org 官方网站下载安装 系统:Windows, Linux or Ma ...
- 微软职位内部推荐-SW Engineer II for Enterprise Platform
微软近期Open的职位: Job posting title: SDE II Location: China, Beijing Group Overview Discovery & Colla ...
- mv命令详解
基础命令学习目录首页 原文链接:https://www.cnblogs.com/piaozhe116/p/6084214.html mv命令是move的缩写,可以用来移动文件或者将文件改名(move ...
- linux后退文件夹命令
后退文件夹: cd - 在重复一遍就是前进了
- Scrum Meeting 4 -2014.11.8
开始了apec的放假,希望大家能处理好工作与休息的时间分配,不要玩疯了啊. 各任务都开始实现了自己的算法,需要部署的服务器我也进去看了看情况,希望最后能部署成功. 最近发现的一些关于上一届实现的问题, ...
- BugPhobia开发篇章:绩效管理的层次优化
0x00 :用0x00去书写一段故事 If you weeped for the missing sunset, you would miss all the shining stars 绩效管理,恐 ...
- 【Coursera】支持向量机
一.最大间隔分类器 1. 函数间隔:\(γ^{i} = y^{i}(w^{T} x + b)\), 改变w和b的量级,对分类结果不会产生任何影响,但是会改变函数间隔的大小.因此,直接对函数间隔求最大值 ...
- 旧文备份:CANopen中SYNC的功能和使用
SYNC是CANopen管理各节点同步数据收发的一种方法,相当于网络节拍,基于同步的PDO按照这个网络节拍来执行实时数据的收发.SYNC属于生产/消费型通讯方式,网络中有且只有一个SYNC生产者,一般 ...
- elicpse
摘自http://blog.csdn.net/bug_love/article/details/72636505 eclipse error pages打红X的解决方法 我每次建一个Maven项目转为 ...