zoukankan      html  css  js  c++  java
  • P5556 圣剑护符

    Luogu

    Description.

    给定一个点带权的无根树,支持:

    • \(\oplus x\)
    • 链查询是否存在两个不同集合他们所有元素 \(\oplus\) 值相等。

    Solution.

    直接转化成是否存在一个集合它所有元素 \(\oplus\) 起来是 \(0\)
    \(\log^3 n\) 做法很显然,直接 \(\log ^2\) 线性基合并即可。
    然后 \(\log ^3 \rightarrow \log ^2\) 直接考虑当链 \(\ge 30\) 时肯定有解。
    考虑鸽笼原理,有 \(n\) 个点的链有 \(2^n\) 种选择,如果 \(2^n\ge V\) 必然有相同。
    所以就俩 \(\log \,\) 啦!!

    小 tips:树剖不需要用线段树直接树状数组就行了的说

    Coding.

    点击查看 /dao 代码
    //是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
    #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...);}//}}}
    const int N=1000005;int n,Q,a[N],xj[35],T[N];
    struct edge{int to,nxt;}e[N<<1];int et,head[N];
    inline void adde(int x,int y) {e[++et]=(edge){y,head[x]},head[x]=et;}
    int dep[N],sz[N],sn[N],f[N],dfn[N],nfd[N],tp[N],dt;
    inline void dfs0(int x,int fa)
    {
    	sz[x]=1,dep[x]=dep[fa]+1,f[x]=fa;
    	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)
    {
    	dfn[x]=++dt,nfd[dt]=x,tp[x]=top;if(sn[x]) dfs1(sn[x],top);
    	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 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;
    }
    inline int dis(int x,int y) {return dep[x]+dep[y]-(dep[LCA(x,y)]<<1);}
    inline void modif(int x,int w) {for(;x<=n;x+=x&(-x)) T[x]^=w;}
    inline int query(int x) {int r=0;for(;x;x-=x&(-x)) r^=T[x];return r;}
    inline void update(int x,int y,int c)
    {
    	for(;tp[x]^tp[y];x=f[tp[x]])
    	{
    		if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
    		modif(dfn[tp[x]],c),modif(dfn[x]+1,c);
    	}
    	if(dfn[x]>dfn[y]) swap(x,y);
    	modif(dfn[x],c),modif(dfn[y]+1,c);
    }
    inline void ins(int x) {for(int i=30;~i;i--) if((x>>i)&1) {if(xj[i]) x^=xj[i];else return xj[i]=x,void();}xj[31]=1;}
    int main()
    {
    	read(n),read(Q);for(int i=1;i<=n;i++) read(a[i]);
    	for(int i=1,x,y;i<n;i++) read(x,y),adde(x,y),adde(y,x);
    	dfs0(1,0),dfs1(1,0);for(int i=1;i<=n;i++) modif(dfn[i],a[i]),modif(dfn[i]+1,a[i]);
    	for(int x,y,z;Q--;)
    	{
    		char ch[10];scanf("%s",ch);read(x,y);
    		if(*ch=='U') {read(z),update(x,y,z);continue;}
    		if(dis(x,y)>=30) {puts("YES");continue;}
    		memset(xj,0,sizeof(xj));int lc=LCA(x,y);ins(query(dfn[lc]));
    		while(x^lc) ins(query(dfn[x])),x=f[x];
    		while(y^lc) ins(query(dfn[y])),y=f[y];
    		puts(xj[31]?"YES":"NO");
    	}return 0;
    }
    
  • 相关阅读:
    XO Wave-数字音频编纂软件
    LSS:撰写 LaTeX 的扶直对象
    Ubuntu 推出能主动装置编码器、Flash、Java、MS 字体的新包
    目前国内主要有4家“播客”网站
    开始换用 Delphi 2009
    关于 Delphi 中流的使用(10): 压缩与解压缩进度 回复 "ilst" 的问题
    试试带参数的 Exit
    在 Delphi 中调用 JavaScript(2)
    在 Delphi 中调用 JavaScript(1) 回复 "fancy" 的问题
    如何获取重载函数的地址 回复 "flq_00000" 的问题
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15366890.html
Copyright © 2011-2022 走看看