zoukankan      html  css  js  c++  java
  • [SCOI2016]幸运数字

    \(\text{Solution}\)

    很显然的暴力就是把路径上的数抽出来弄个线性基求答案
    再优化一下就是用倍增的方式把数抽出来
    倍增时涉及两个线性基合并,然后就是 \(O(3600q\log n)\)
    竟没想到它可以过

    \(\text{Code}\)

    #include <cstdio>
    #include <iostream>
    #define RE register
    #define IN inline
    using namespace std;
    typedef long long LL;
    
    const int N = 20005;
    int n, q, fa[N][16], h[N], tot, dep[N];
    LL a[N];
    struct edge{int to, nxt;}e[N << 1];
    IN void add(int x, int y){e[++tot] = edge{y, h[x]}, h[x] = tot;}
    
    struct node{
    	LL p[61];
    	IN node(){for(RE int i = 0; i < 61; i++) p[i] = 0;}
    }f[N][16];
    IN void Insert(node &a, LL x)
    {
    	for(RE int i = 60; i >= 0; i--)
    		if ((x >> i) & 1)
    		{
    			if (!a.p[i]){a.p[i] = x; return;}
    			x ^= a.p[i];
    		}
    }
    IN void Merge(node &a, node b)
    {
    	for(RE int i = 60; i >= 0; i--)
    		if (b.p[i]) Insert(a, b.p[i]);
    }
    
    void dfs(int x, int dad)
    {
    	for(RE int i = 1; i <= 15; i++)
    	if (fa[x][i - 1]) fa[x][i] = fa[fa[x][i - 1]][i - 1],
    		Merge(f[x][i], f[x][i - 1]), Merge(f[x][i], f[fa[x][i - 1]][i - 1]);
    	else break;
    	for(RE int i = h[x]; i; i = e[i].nxt)
    	{
    		int v = e[i].to;
    		if (v == dad) continue;
    		Insert(f[v][0], a[v]), fa[v][0] = x, dep[v] = dep[x] + 1;
    		dfs(v, x);
    	}
    }
    IN node Query(int u, int v)
    {
    	node tmp;
    	if (dep[u] < dep[v]) swap(u, v);
    	int deep = dep[u] - dep[v];
    	for(RE int i = 15; i >= 0; i--)
    		if ((deep >> i) & 1) Merge(tmp, f[u][i]), u = fa[u][i];
    	if (u == v){Insert(tmp, a[u]); return tmp;}
    	for(RE int i = 15; i >= 0; i--)
    	if (fa[u][i] ^ fa[v][i])
    		Merge(tmp, f[u][i]), Merge(tmp, f[v][i]), u = fa[u][i], v = fa[v][i];
    	Insert(tmp, a[u]), Insert(tmp, a[v]), Insert(tmp, a[fa[u][0]]);
    	return tmp;
    }
    
    IN void read(int &x)
    {
    	x = 0; char ch = getchar();
    	for(; !isdigit(ch); ch = getchar());
    	for(; isdigit(ch); x = (x<<3)+(x<<1)+(ch^48), ch = getchar());
    }
    IN void readLL(LL &x)
    {
    	x = 0; char ch = getchar();
    	for(; !isdigit(ch); ch = getchar());
    	for(; isdigit(ch); x = (x<<3)+(x<<1)+(ch^48), ch = getchar());
    }
    
    int main()
    {
    	read(n), read(q);
    	for(RE int i = 1; i <= n; i++) readLL(a[i]);
    	for(RE int i = 1, u, v; i < n; i++) read(u), read(v), add(u, v), add(v, u);
    	dfs(1, 0); node tmp; LL ans;
    	for(RE int u, v; q; --q)
    	{
    		read(u), read(v), tmp = Query(u, v), ans = 0;
    		for(RE int i = 60; i >= 0; i--) ans = max(ans, ans ^ tmp.p[i]);
    		printf("%lld\n", ans);
    	}
    }
    
  • 相关阅读:
    【143】360云盘资源
    【142】阿蛮歌霸使用技巧
    [置顶] 程序员必知(三):一分钟知道URI编码(encodeURI)
    [置顶] Oracle job procedure 存储过程定时任务
    浅析动态表单
    DoctorNote医生处方笔记开发记录
    Step2:配置Oracle Dataguard
    IOS开发UIImage中stretchableImageWithLeftCapWidth方法的解释
    解析客户端脚本、服务器端脚本
    tomcat目录结构
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/15759221.html
Copyright © 2011-2022 走看看