zoukankan      html  css  js  c++  java
  • 题解 P3292 【[SCOI2016]幸运数字】

    题目链接

    Solution [SCOI2016]幸运数字

    题目大意:给定一棵树,每次询问一条路径上的点权的异或最大值

    线性基,倍增


    分析:

    看到一个集合,要求一个子集使得异或值最大我们基本上就可以往线性基上想了

    首先线性基的合并复杂度是(O(logm^2))的,(m)为值域

    于是sbzcy写了个树剖TLE一片

    我们需要考虑优化,由于不带修改,是静态询问,我们考虑用类似求(LCA)的方法,倍增来合并一条路径上的线性基

    注意一下边界问题的处理,以及轻微卡常,请使用读入优化

    #include <cstdio>
    #include <cctype>
    #include <vector>
    using namespace std;
    typedef long long ll;
    const int maxn = 32769,limit = 62,maxdep = 23;
    inline ll read(){
    	ll x = 0;char c = getchar();
    	while(!isdigit(c))c = getchar();
    	while(isdigit(c))x = x * 10 + c - '0',c = getchar();
    	return x;
    }
    struct LB{//线性基
    	ll p[limit + 1];
    	inline ll query()const{
    		ll res = 0;
    		for(int i = limit;i >= 0;i--)
    			if((res ^ p[i]) > res)res ^= p[i];
    		return res;
    	}
    	inline void insert(ll x){
    		for(int i = limit;i >= 0;i--){
    			if(!(x >> i))continue;
    			if(!p[i]){
    				p[i] = x;
    				break;
    			}
    			x ^= p[i];
    		}
    	}
    	inline void merge(const LB &x){
    		for(int i = limit;i >= 0;i--)
    			if(x.p[i])insert(x.p[i]);
    	}
    }f[maxn][maxdep + 1],zero;
    vector<int> G[maxn];
    inline void addedge(int from,int to){
    	G[from].push_back(to);
    }
    int n,q,faz[maxn][maxdep + 1],dep[maxn];
    ll val[maxn];
    void dfs(int u){//预处理倍增
    	dep[1] = 1;
    	f[u][0].insert(val[u]);
    	for(int i = 1;i <= maxdep;i++)
    		f[u][i] = f[u][i - 1],f[u][i].merge(f[faz[u][i - 1]][i - 1]),faz[u][i] = faz[faz[u][i - 1]][i - 1];
    	for(int v : G[u]){
    		if(v == faz[u][0])continue;
    		faz[v][0] = u;
    		dep[v] = dep[u] + 1;
    		dfs(v);
    	}
    }
    inline ll path_query(int x,int y){//查询
    	LB res = zero;
    	if(dep[x] < dep[y])swap(x,y);
    	for(int i = maxdep;i >= 0;i--)
    		if(dep[faz[x][i]] >= dep[y])
    			res.merge(f[x][i]),x = faz[x][i];
    	if(x == y)return res.merge(f[x][0]),res.query();
    	for(int i = maxdep;i >= 0;i--)
    		if(faz[x][i] != faz[y][i]){
    			res.merge(f[x][i]),x = faz[x][i];
    			res.merge(f[y][i]),y = faz[y][i];
    		}
    	res.merge(f[x][0]);
    	res.merge(f[y][0]);
    	res.merge(f[faz[x][0]][0]);
    	return res.query();
    }
    int main(){
    	n = read(),q = read();
    	for(int i = 1;i <= n;i++)val[i] = read();
    	for(int x,y,i = 1;i < n;i++)
    		x = read(),y = read(),addedge(x,y),addedge(y,x);
    	dfs(1);
    	for(int x,y,i = 1;i <= q;i++)
    		x = read(),y = read(),printf("%lld
    ",path_query(x,y));
    	return 0;
    }
    
  • 相关阅读:
    Redis优化经验
    servlet/filter/listener/interceptor区别与联系
    无状态服务(stateless service)
    http请求中java中的302和sendRedirect的区别
    深入ThreadLocal之三(ThreadLocal可能引起的内存泄露)
    Connection reset原因分析和解决方案
    深入ThreadLocal之一
    ThreadLocal的坑--ThreadLocal跨线程传递问题
    MySQL通配符过滤
    六、Linux/UNIX操作命令积累【kill、netstat、df、du】
  • 原文地址:https://www.cnblogs.com/colazcy/p/11515173.html
Copyright © 2011-2022 走看看