zoukankan      html  css  js  c++  java
  • CF840E In a Trap

    一、题目

    点此看题

    二、解法

    感冒在家两天,今天才回学校,虽然博客鸽了一天但是我换签名了

    对于询问其实可以分块,每一块的前 \(8\) 位都是一样的,那么处理后 \(8\) 位就可以了,设 \(f(u,i)\) 表示 \(u\) 向上的 \(256\) 个节点中,最大的 \(a_v\oplus (dep_u-dep_v)\oplus (i\cdot 256)\),那么查询可以先跳整块再跳散块。

    对于上面这东西显然可以值域分治,对于前 \(8\) 位我们可以搞一个 \(\tt trie\) 树直接查询。对于后 \(8\) 位我们开一个桶 \(g(u,i)\) 表示前 \(8\) 位为 \(i\)\(a_v\),最大的 \(((dep_u-dep_v)\oplus a_v)\and 256\),那么 \(f(u,i)\) 就可以通过这两者拼凑出来。

    预处理的复杂度是 \(O(n\log n\sqrt n)\),询问的复杂度是 \(O(q\sqrt n)\)

    三、总结

    看到 \(a_i\leq n\) 之类的限制多半要用到值域分块,对于加法和异或的混合问题可以考虑对半拆位。

    #include <cstdio>
    #include <vector>
    #include <iostream>
    using namespace std;
    const int M = 50005;
    const int N = 256;
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int n,m,a[M],fa[M],dep[M],f[M][260],mx[M][260];
    vector<int> g[M];int cnt,ch[M][2],lst[M];
    void upd(int &x,int y) {x=max(x,y);}
    void ins(int x)
    {
    	for(int i=7,p=1;i>=0;i--)
    	{
    		int w=(x>>i)&1;
    		if(!ch[p][w]) ch[p][w]=++cnt;
    		p=ch[p][w];
    	}
    }
    int ask(int x,int u)
    {
    	int v=0,res=0;
    	for(int i=7,p=1;i>=0;i--)
    	{
    		int w=((x>>i)&1)^1;
    		if(ch[p][w]) p=ch[p][w],res|=(1<<i);
    		else p=ch[p][w^=1];
    		v|=(w<<i);
    	}
    	return (res<<8)|mx[u][v];
    }
    void dfs(int u)
    {
    	if(dep[u]>=N)
    	{
    		for(int i=1;i<=cnt;i++) ch[i][0]=ch[i][1]=0;
    		cnt=1;int i=u;
    		for(;dep[u]-dep[i]<N;i=fa[i])
    		{
    			upd(mx[u][a[i]>>8],(dep[u]-dep[i]^a[i])&255);
    			ins(a[i]>>8);
    		}
    		lst[u]=i;
    		for(i=0;i<N;i++) f[u][i]=ask(i,u);
    	}
    	for(auto v:g[u]) if(v^fa[u])
    		fa[v]=u,dep[v]=dep[u]+1,dfs(v);
    }
    signed 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();
    		g[u].push_back(v);
    		g[v].push_back(u);
    	}
    	dep[1]=1;dfs(1);
    	for(int i=1;i<=m;i++)
    	{
    		int u=read(),v=read(),ans=0,d=0;
    		for(;dep[v]-dep[u]>=N;v=lst[v],d++) ans=max(ans,f[v][d]);
    		for(d<<=8;v!=fa[u];v=fa[v],d++) ans=max(ans,d^a[v]);
    		printf("%d\n",ans);
    	}
    }
    
  • 相关阅读:
    win7网络共享原来如此简单,WiFi共享精灵开启半天都弱爆了!
    JQUERY UI Datepicker Demo
    Official online document, install svn server in centOS
    JAVE not work in linux
    AMR 转mp3 失败
    XD, XR, DR 股票
    Linux 下MySql 重置密码
    Difinition Of Done
    Apache, Tomcat, JK Configuration Example
    Linux 安装tomcat
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/15787730.html
Copyright © 2011-2022 走看看