• CF1479D Odd Mineral Resource 题解


    Codeforces
    Luogu

    Description.

    给定一棵树,每个点有颜色 (c_i) ,多次查询,每次给定 (u,v,l,r)
    你需要给出一个颜色 (x(xin[l,r])),使得 (x)(u)(v) 的路径上出现奇数次。

    Solution.

    奇数次可以想到 (oplus)
    给每个颜色赋一个随机权值,然后判断区间是否存在 (oplus) 不为 (0)
    可以主席树乱杀。
    然后就做完了。

    Coding.

    点击查看代码
    //Coded by Kamiyama_Shiki on 2021.11.09 {{{
    //是啊……你就是那只鬼了……所以被你碰到以后,就轮到我变成鬼了
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),f=0;
    	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
    	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	f?x=-x:x;
    }
    template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}}
    typedef unsigned long long ull;mt19937_64 myrand(114);
    const int N=300005;int n,m,a[N],rt[N];ull cv[N];
    namespace zzt
    {
    	struct seg{int ls,rs;ull xr;}T[6300005];int tt;
    	inline void build(int &x,int y,int l,int r,int dw,ull dc)
    	{
    		T[x=++tt]=T[y],T[x].xr^=dc;if(l==r) return;
    		if(dw<=((l+r)>>1)) build(T[x].ls,T[y].ls,l,(l+r)>>1,dw,dc);
    		else build(T[x].rs,T[y].rs,((l+r)>>1)+1,r,dw,dc);
    	}
    	inline int qry(int x,int y,int z,int w,int l,int r,int dl,int dr)
    	{
    		if(l>dr||dl>r||!(T[x].xr^T[y].xr^T[z].xr^T[w].xr)) return -1;else if(l==r) return l;
    		int v;if(~(v=qry(T[x].ls,T[y].ls,T[z].ls,T[w].ls,l,(l+r)>>1,dl,dr))) return v;
    		return qry(T[x].rs,T[y].rs,T[z].rs,T[w].rs,((l+r)>>1)+1,r,dl,dr);
    	}
    }
    struct edge{int to,nxt;}e[N<<1];int et,head[N];
    int dep[N],sn[N],sz[N],f[N],tp[N];
    inline void adde(int x,int y) {e[++et]=(edge){y,head[x]},head[x]=et;}
    inline void dfs0(int x,int fa)
    {
    	dep[x]=dep[f[x]=fa]+1,sz[x]=1,sn[x]=0;
    	for(int i=head[x];i;i=e[i].nxt) if(e[i].to!=fa)
    	{
    		dfs0(e[i].to,x),sz[x]+=sz[e[i].to];
    		if(sz[e[i].to]>sz[sn[x]]) sn[x]=e[i].to;
    	}
    }
    inline void dfs1(int x,int top)
    {
    	tp[x]=top;if(sn[x]) dfs1(sn[x],top);else return;
    	for(int i=head[x];i;i=e[i].nxt) if(e[i].to!=f[x]&&e[i].to!=sn[x]) dfs1(e[i].to,e[i].to);
    }
    inline void dfs2(int x,int fa)
    {
    	zzt::build(rt[x],rt[fa],1,n,a[x],cv[a[x]]);
    	for(int i=head[x];i;i=e[i].nxt) if(e[i].to!=fa) dfs2(e[i].to,x);
    }
    inline int LCA(int x,int y)
    {
    	for(;tp[x]^tp[y];x=f[tp[x]]) if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
    	return dep[x]<dep[y]?x:y;
    }
    int main()
    {
    	read(n,m);for(int i=1;i<=n;i++) read(a[i]),cv[i]=myrand();
    	for(int i=1,x,y;i<n;i++) read(x,y),adde(x,y),adde(y,x);
    	dfs0(1,0),dfs1(1,1),dfs2(1,0);
    	for(int i=1,x,y,l,r;i<=m;i++)
    	{
    		read(x,y,l,r);int lc=LCA(x,y);
    		printf("%d
    ",zzt::qry(rt[x],rt[y],rt[lc],rt[f[lc]],1,n,l,r));
    	}return 0;
    }
    
  • 相关阅读:
    预处理命令
    函数
    结构体
    字符数组
    数组
    文件
    用 typedef 定义类型
    枚举类型
    联合
    位运算
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15528920.html
Copyright © 2020-2023  润新知