4568: [Scoi2016]幸运数字

Time Limit: 60 Sec  Memory Limit: 256 MB
Submit: 848  Solved: 336
[Submit][Status][Discuss]

Description

A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一。每座城市都有一个
幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征。一些旅行者希望游览 A 国。旅行者计划
乘飞机降落在 x 号城市,沿着 x 号城市到 y 号城市之间那条唯一的路径游览,最终从 y 城市起飞离开 A 国。
在经过每一座城市时,游览者就会有机会与这座城市的幸运数字拍照,从而将这份幸运保存到自己身上。然而,幸
运是不能简单叠加的,这一点游览者也十分清楚。他们迷信着幸运数字是以异或的方式保留在自己身上的。例如,
游览者拍了 3 张照片,幸运值分别是 5,7,11,那么最终保留在自己身上的幸运值就是 9(5 xor 7 xor 11)。
有些聪明的游览者发现,只要选择性地进行拍照,便能获得更大的幸运值。例如在上述三个幸运值中,只选择 5 
和 11 ,可以保留的幸运值为 14 。现在,一些游览者找到了聪明的你,希望你帮他们计算出在他们的行程安排中
可以保留的最大幸运值是多少。
 
lyd说这道题维护倍增数组后暴力合并就可以。
于是。。。。
 
我不是有意要卡评测啊啊啊啊

然后发现果然合并有更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]幸运数字的更多相关文章

  1. BZOJ 4568: [Scoi2016]幸运数字 [线性基 倍增]

    4568: [Scoi2016]幸运数字 题意:一颗带点权的树,求树上两点间异或值最大子集的异或值 显然要用线性基 可以用倍增的思想,维护每个点向上\(2^j\)个祖先这些点的线性基,求lca的时候合 ...

  2. BZOJ 4568 [Scoi2016]幸运数字(树链剖分 + 异或线性基)

    题目链接  BZOJ 4568 考虑树链剖分+线段树维护每一段区域的异或线性基 对于每个询问,求出该点集的异或线性基.然后求一下这个线性基里面能异或出的最大值即可. #include <bits ...

  3. bzoj 4568: [Scoi2016]幸运数字【树链剖分+线段树+线性基】

    一眼做法,好处是好想好写坏处是常数大,容易被卡(bzoj loj 洛谷开O2 能AC,不开有90分-- 大概就是树剖之后维护线段树,在线段树的每个节点上上维护一个线性基,暴力\( 60^2 \)的合并 ...

  4. BZOJ 4568 [Scoi2016]幸运数字 ——线性基 倍增

    [题目分析] 考虑异或的最大值,维护线性基就可以了. 但是有多次的询问,树剖或者倍增都可以. 想了想树剖动辄数百行的代码. 算了,我还是写倍增吧. 注:被位运算和大于号的优先级坑了一次,QaQ [代码 ...

  5. BZOJ 4568: [Scoi2016]幸运数字(倍增+线性基)

    传送门 解题思路 异或最大值肯定线性基了,树上两点那么就倍增搞一搞,就维护每个点到各级祖先的线性基,时间复杂度\(O(nlog^3n)\),并不知道咋过去的. 代码 #include<iostr ...

  6. 【BZOJ 4568】 4568: [Scoi2016]幸运数字 (线性基+树链剖分+线段树)

    4568: [Scoi2016]幸运数字 Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个 幸运数字,以纪念碑的形 ...

  7. BZOJ.4516.[SCOI2016]幸运数字(线性基 点分治)

    题目链接 线性基可以\(O(log^2)\)暴力合并.又是树上路径问题,考虑点分治. 对于每个点i求解 LCA(u,v)==i 时的询问(u,v),只需求出这个点到其它点的线性基后,暴力合并. LCA ...

  8. [BZOJ4568][Scoi2016]幸运数字 倍增+线性基

    4568: [Scoi2016]幸运数字 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1791  Solved: 685[Submit][Statu ...

  9. [BZOJ4568][SCOI2016]幸运数字(倍增LCA,点分治+线性基)

    4568: [Scoi2016]幸运数字 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 2131  Solved: 865[Submit][Statu ...

随机推荐

  1. python 原生态调用server服务————SimpleHTTPServer

    python 原生态调用server服务,接收http传递的参数并且处理返回结果 很多blog中都是抄了官网的,没有说明参数如何接收 1.代码中提供了post与get两种方式来发起请求,但是传递参数时 ...

  2. 互评Beta版本——杨老师粉丝群——Pinball

    互评beta版本    杨老师粉丝群——<PinBall> 一.基于NABCD评论作品,及改进建议 1.根据(不限于)NABCD评论作品的选题 (1)N(Need,需求) 随着年龄的增长, ...

  3. Daily Scrumming* 2015.10.31(Day 12)

    一.今明两天任务表 Member Today’s Task Tomorrow’s Task 江昊 学习rails的HTTP控制 继续学习rails等项目工具 杨墨犁 学习semanticUI的用法,配 ...

  4. eclipse自动生成uml

    见如下链接: https://blog.csdn.net/zyf_balance/article/details/44937197 若eclipse无法生成,可以安装myeclipse使用自带的方法: ...

  5. 20172325 2016-2017-2 《Java程序设计》第四周学习总结

    20172325 2016-2017-2 <Java程序设计>第四周学习总结 教材学习内容总结 1.对类.对象.声明变量的定义和属性有了进一步的了解 2.学会如何编写一个类并运用到需要的程 ...

  6. Chapter 1 概述

    软件分为通用软件和应用软件,具有复杂.不可见和不断变化的特点:从出现到现在共经历了四个重要的发展阶段,但现在的软件发展依然存在着许多问题. 软件工程是采用工程的概念.原理.技术和方法来开发与维护软件, ...

  7. poi读取、通过poi导出数据库的记录到excl表

    package com.nt.test;   import java.io.File; import java.io.FileInputStream; import java.io.FileNotFo ...

  8. mysql非安装包安装教程

    设置mysql的环境变量 本人设置安装的路径是:E:\WebApplication\webMySQL\mysql-5.7.13-winx64 我的电脑 ---> 高级系统配置 ---> 环 ...

  9. 结对项目作业GUI

    一.Coding.Net项目地址:https://git.coding.net/zhengsh589/CoupleProject.git 二.PSP表格(完成前): PSP 任务内容 计划共完成需要的 ...

  10. Keil C51 的printf

    转自:http://blog.csdn.net/zhanglianpin/article/details/44779009 在Keil C51 中使用printf ,首先需要重新实现 putchar( ...