• BZOJ4568 [Scoi2016]幸运数字


    BZOJ4568 [Scoi2016]幸运数字


    题目描述

    传送门

    题目分析

    这个题,求树上链的(XOR)最大值,可以不选某些点。

    考虑到线性基可以用很快的速度求出(XOR)的最大值,我们首先可以确定使用线性基来搞定这个题的询问。

    然后可以考虑用树剖解决,发现一个问题,使用树剖时,由于一边跳一遍计算线性基,还要合并,复杂度比较高,虽然的确可以通过本题,但是明显可以通过随便增大数据就卡死了。倍增貌似拥有更好的常数,但是,空间利用太低,容易(MLE)

    发现每次询问只询问链,那么我们可以使用LCT点分治来解决这个题。

    具体方法就是,我们点分治计算每个子树的时候,把询问中lca是这个子树的根的直接求出来然后合并,不是的就把询问传下去,这样复杂度就是(O(Nlog^2N))的,非常优秀可以通过。

    是代码呢

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN=2e5+7;
    #define ll long long
    const ll inf=1ll<<61;
    ll n,m,a[MAXN],p[MAXN],ans[MAXN],size[MAXN],wson[MAXN],vis[MAXN],U[MAXN],V[MAXN],bel[MAXN],tq[MAXN],sum,root;
    bool use[MAXN];
    inline ll read()
    {
        ll x=0,c=1;
        char ch=' ';
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        while(ch=='-')c*=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*c;
    }
    vector<int> edge[MAXN],q[MAXN];
    struct T{
    	ll b[65];
    	inline void clear() {memset(b,0,sizeof(b));}
    	inline void insert(ll x){
    		for(int i=60;~i;i--)
    			if(x>>i&1){
    				if(b[i]) x^=b[i];
    				else {b[i]=x;break;}
    			}
    	}
    	inline void merge(const T &x){
    		for(int i=60;~i;i--){
    			if(x.b[i]) insert(x.b[i]);
    		}
    	}
    	inline ll query(){
    		ll ans=0;
    		for(int i=60;~i;i--){
    			if((ans^b[i])>ans) ans^=b[i];
    		}
    		return ans;
    	}
    }base[MAXN];
    inline void get_root(int u,int fa)
    {
    	size[u]=1;wson[u]=0;
    	for(int i=0;i<edge[u].size();i++){
    		int v=edge[u][i];
    		if(v==fa||vis[v]) continue;
    		get_root(v,u);
    		size[u]+=size[v];
    		if(wson[u]<size[v]) wson[u]=size[v];
    	}
    	if(sum-size[u]>wson[u]) wson[u]=sum-size[u];
    	if(wson[u]<wson[root]) root=u;
    }
    
    inline void dfs(int u,int fa,int tt){
    	base[u]=base[fa]; bel[u]=tt;base[u].insert(a[u]);
    	for(int i=0;i<edge[u].size();i++){
    		int v=edge[u][i];
    		if(v!=fa&&!vis[v]) dfs(v,u,tt);
    	}
    }
    
    inline void solve(int x){
    	if(!q[x].size()) return;
    	wson[0]=inf;sum=size[x];root=0;
    	get_root(x,0);
    	int u=root;
    	vis[root]=1;bel[root]=root;
    	base[root].clear();base[root].insert(a[root]);
    	for(int i=0;i<edge[root].size();i++){
    		int v=edge[root][i];
    		if(!vis[v]) dfs(v,root,v);
    	}
    	int tot=q[x].size();
    	for(int i=0;i<tot;i++) tq[i]=q[x][i];
    	q[x].clear();
    	T tmp;ll id;
    	for(int i=0;i<tot;i++){
    		id=tq[i];
    		if(bel[U[id]]==bel[V[id]])
    			q[bel[U[id]]].push_back(id);
    		else tmp=base[U[id]],tmp.merge(base[V[id]]),ans[id]=tmp.query(),use[id]=1;
    	}
    	for(int i=0;i<edge[u].size();i++){
    		int v=edge[u][i];
    		if(vis[v]) continue;
    		solve(v);
    	}
    }
    int main()
    {
    	n=read();m=read();
    	for(int i=1;i<=n;i++) a[i]=read();
    	for(int i=1;i<n;i++){
    		int u=read(),v=read();
    		edge[u].push_back(v);
    		edge[v].push_back(u);
    	}
    	for(int i=1;i<=m;i++){
    		U[i]=read();V[i]=read();
    		if(U[i]==V[i]) ans[i]=a[U[i]];
    		else q[1].push_back(i);
    	}
    	size[1]=n;solve(1);
    	for(int i=1;i<=m;i++) printf("%lld
    ", ans[i]);
    }
    
  • 相关阅读:
    servlet基础讲解
    tomcat web.xml配置
    JavaScript Cookies
    窗口的自适应处理
    让Eclipse和NetBeans共享同一个项目
    maven基础知识
    JS中令人发指的valueOf方法介绍
    在iOS开发中使用FMDB
    苹果开发者账号那些事儿(三)
    苹果开发者账号那些事儿(二)
  • 原文地址:https://www.cnblogs.com/victorique/p/10277988.html
Copyright © 2020-2023  润新知