[NOI.AC#41]最短路 线性基
题解
如果不加边,两个点之间的长度是唯一的(只能走最短路径),因为如果重复走,就异或掉了。
因此,先DFS预处理一下每个点到根的距离 \(d[x]\) ,那么 \(x,y\) 之间的距离为 $d[x] \oplus d[y] $
对于每条新建的边 \((u,v,w)\) ,它实际上增加了一个环,如果没有范围限制,那就变成了[WC2011]最大XOR和路径(BZOJ2115)。
按照它的思路,我们对每个环(权值为 \(W[i]=d[u[i]]\oplus d[v[i]]\oplus w[i]\))构造线性基,考虑如何保证满足范围限制
将询问离线,并根据右端点排序(挂链表),然后按顺序扫描边数组 \(W[i]\) ,对于二进制基底 \(p[i]\) ,定义 \(q[i]\) 为它的位置,显然为了满足范围限制, \(q[i]\) 越大越好。因此从大到小枚举 \(i\) ,每遇到一个 \(q[i]\) 比当前位置小的,我们将其与之交换,然后多出来的 \(p[i]\) 再往下插入线性基。
处理答案时,从高位向低位贪心,如果 \(q[i]\) 在范围内就可以加入。
#include<bits/stdc++.h>
#define REP(i,a,b) for(int i(a);i<=(b);++i)
#define dbg(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int,int>pii;
template<typename T,typename U>inline char smin(T&x,const U&y){return x>y?x=y,1:0;}
template<typename T,typename U>inline char smax(T&x,const U&y){return x<y?x=y,1:0;}
namespace IOManager{
	const unsigned int iSize(131072),oSize(65536);
	char buf[iSize],wbuf[oSize+128],*iT=buf+iSize,*iS=iT-1,*oS=wbuf-1,*oT=wbuf+oSize;
	struct FastIO{
		inline char gc(){
			if(++iS==iT)fread(iS=buf,1,iSize,stdin);return *iS;
		}
		template<typename T>
			inline void read(T&w){register char c,p=0;
				while(isspace(c=gc()));if(c=='-')p=1,c=gc();w=c^48u;
				while(isdigit(c=gc()))w=w*10+(c^48u);if(p)w=-w;
			}
		inline int read(){register int x;return read(x),x;}
		inline void flush(){fwrite(wbuf,1,oS-wbuf+1,stdout);oS=wbuf-1;}
		~FastIO(){flush();}
		inline FastIO&operator<<(const char&c){if(oS>oT)flush();*++oS=c;}
		inline void putstr(const string&s){
			const int l=s.length();
			if(oS>oT)flush();
			for(int i=0;i<l;++i)*++oS=s[i];
		}
		template<typename T>
			inline FastIO&operator<<(T x){
				static char stk[30];int top=0;
				if(oS>oT)flush();
				if(x==0)return *++oS='0',*this;
				if(x<0)x=-x,*++oS='-';
				for(;x;x/=10)stk[++top]=x%10^48;
				while(top)*++oS=stk[top--];
				return*this;
			}
	};
}IOManager::FastIO io;
#define read io.read
const int n=read(),m=read(),Q=read(),N=3e5+5;
vector<int>g[N];
int head[N],tot,d[N],w[N],r[N],l[N],p[33],q[33],ans[N];
struct node{int v,w,nxt;}e[N<<1];
inline void add(int x,int y,int z){e[++tot]=(node){y,z,head[x]};head[x]=tot;}
inline void dfs(int x,int fa){for(int i=head[x];i;i=e[i].nxt)if(e[i].v!=fa)d[e[i].v]=d[x]^e[i].w,dfs(e[i].v,x);}
int main(){
	REP(i,2,n){
		int x=read(),y=read(),z=read();
		add(x,y,z),add(y,x,z);
	}
	dfs(1,0);
	REP(i,1,m)w[i]=d[read()]^d[read()]^read();
	REP(i,1,Q){
		ans[i]=d[read()]^d[read()];l[i]=read();g[read()].push_back(i);
	}
	REP(t,1,m){
		int x=w[t],r=t;
		for(int i=30;~i;--i)if(x>>i&1){
			if(!p[i]){p[i]=x,q[i]=r;break;}
			if(q[i]<r)swap(p[i],x),swap(q[i],r);
			x^=p[i];
		}
		for(int k:g[t])for(int i=30;~i;--i)if(q[i]>=l[k])smin(ans[k],ans[k]^p[i]);
	}
	REP(i,1,Q)io<<ans[i]<<'\n';
	return 0;
}
												
											[NOI.AC#41]最短路 线性基的更多相关文章
- NOIAC41 最短路(线性基)
		
/* 暴力可以st表维护线性基, 从而复杂度两个log 实际上我们可以离线来做, 并且记录可行最右值, 就是一个log的了 */ #include<cstdio> #include< ...
 - BZOJ_2844 albus就是要第一个出场 【线性基】
		
一.题目 albus就是要第一个出场 二.分析 非常有助于理解线性基的一题. 构造线性基$B$后,如果$|A| > |B|$,那么就意味着有些数可以由$B$中的数异或出来,而多的数可以取或者不取 ...
 - BZOJ_2115 [Wc2011] Xor 【图上线性基】
		
一.题目 [Wc2011] Xor 二.分析 比较有意思的一题,这里也学到一个结论:$1$到$N$的任意一条路径异或和,可以是一个任意一条$1$到$N$的异或和与图中一些环的异或和组合得到.因为一个数 ...
 - HDU_3949 XOR 【线性基】
		
一.题目 XOR 二.分析 给定$N$个数,问它的任意子集异或产生的数进行排列,求第K小的数. 构造出线性基$B$后,如果$|B| < N$,那么代表N个数中有一个数是可以由线性基中的其他数异或 ...
 - BZOJ 2844 albus就是要第一个出场 ——高斯消元 线性基
		
[题目分析] 高斯消元求线性基. 题目本身不难,但是两种维护线性基的方法引起了我的思考. void gauss(){ k=n; F(i,1,n){ F(j,i+1,n) if (a[j]>a[i ...
 - SCOI2016幸运数字(树剖/倍增/点分治+线性基)
		
题目链接 loj luogu 题意 求树上路径最大点权异或和 自然想到(维护树上路径)+ (维护最大异或和) 那么有三种方法可以选择 1.树剖+线性基 2.倍增+线性基 3.点分治+线性基 至于线性基 ...
 - ACM-ICPC 2017 Asia Xi'an A XOR (线性基+线段树思想)
		
题目链接 题意;给个数组,每次询问一个区间你可以挑任意个数的数字异或和 然后在或上k的最大值 题解:线性基不知道的先看这个,一个线性基可以log的求最大值把对应去区间的线性基求出来然后用线段树维护线性 ...
 - Codeforces 938G Shortest Path Queries [分治,线性基,并查集]
		
洛谷 Codeforces 分治的题目,或者说分治的思想,是非常灵活多变的. 所以对我这种智商低的选手特别不友好 脑子不好使怎么办?多做题吧-- 前置知识 线性基是你必须会的,不然这题不可做. 推荐再 ...
 - 51Nod1577 异或凑数 线性基 构造
		
国际惯例的题面:异或凑出一个数,显然是线性基了.显然我们能把区间[l,r]的数全都扔进一个线性基,然后试着插入w,如果能插入,则说明w不能被这些数线性表出,那么就要输出"NO"了. ...
 
随机推荐
- linux基础入门(二)命令
			
原创作品,允许转载,转载时请务必声明作者信息和本声明. https://www.cnblogs.com/zhu520/p/10732334.html =[本人小白,有错指出.谢谢! 一:使用Secur ...
 - ArcGIS api for javascript——地理编码任务-地理编码地址
			
描述 本例允许用户输入一个地址,然后显示匹配的地址的位置.这通常地被称为地理编码.在ArcGIS JavaScript API中,使用Locator类执行地理编码. 定位器构造函数需要ArcGIS S ...
 - Android布局文件的载入过程分析:Activity.setContentView()源代码分析
			
大家都知道在Activity的onCreate()中调用Activity.setContent()方法能够载入布局文件以设置该Activity的显示界面.本文将从setContentView()的源代 ...
 - 转:Mac下搭建svn服务器和XCode配置svn
			
Mac下搭建svn服务器和XCode配置svn 先打开命令行终端. 1.创建svn repository svnadmin create /yourpath/svnroot/repository 2. ...
 - HNU13303 Counting substhreengs(递推)
			
题目:http://acm.hnu.cn/online/? action=problem&type=show&id=13303&courseid=0 题意:给你一个字符串,由数 ...
 - Effective C++ Item 30 inline里里外外
			
本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie Item 44 46 1.将大多数 inlining 限制在小型.被频繁调用的函数身上.这可 ...
 - mahout处理路透社语料步骤,转换成须要的格式
			
首先下载路透社语料(百度就能够下载): 然后上传Linux 并解压到指定文件夹.Tips:此处我放在可 /usr/hadoop/mahout/reutersTest/reuters tar -zxvf ...
 - QThread 爬坑之旅(三种办法解决QObject: Cannot create children for a parent that is in a different thread)
			
Cannot create children for a parent that is in a different thread. 在Qt的官方文档,大家知道有两种方式使用QThread. You ...
 - vue7 下拉列表
			
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
 - vim 基础学习之文件跳转
			
1. ''-当前文件上次跳转之前的位置2. '.-当前文件上次修改的位置,只要是发生了可能导致变化的命令操作就会被标记,哪怕实际结果没有变化3. '^-当前文件上次插入的位置,只要是发生了插入操作命令 ...