zoukankan      html  css  js  c++  java
  • [Lydsy1805月赛]对称数 BZOJ5361

    分析:

    这个题,还是蛮有趣的。考虑,如果l,r区间内的所有数出现奇数次,那么[l-1,r]的抑或和等于所得抑或和。

    之后怎么维护呢,主席树维护区间抑或和,记得将每个点附上一个ull级别的随机数,之后抑或的结果冲突的概率就几乎没有了。

    lca什么的,随便求。

    剩下的,考虑二分答案,如果左区间的全为奇数个,就往右走,反之往左走。

    附上代码:

    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <iostream>
    using namespace std;
    #define N 205005
    #define lson l,m,tr[rt].ls
    #define rson m+1,r,tr[rt].rs
    #define ll unsigned long long
    #define clear(rt) tr[rt].ls=tr[rt].rs=tr[rt].sum=0;
    struct node
    {
    	int ls,rs;
    	ll sum;
    }tr[N*20];
    struct no
    {
    	int to,next;
    }e[N<<1];
    int dep[N],rot[N],fa[N],anc[N],siz[N],son[N],head[N],cnt,a[N],n,maxn,Q;ll val[N];
    void add(int x,int y)
    {
    	e[++cnt].to=y;
    	e[cnt].next=head[x];
    	head[x]=cnt;
    }
    void insert(int x,int v,ll c,int l,int r,int &rt)
    {
    	rt=++cnt;clear(rt);tr[rt].sum=tr[x].sum^c;
    	if(l==r)return;int m=(l+r)>>1;
    	if(m>=v)tr[rt].rs=tr[x].rs,insert(tr[x].ls,v,c,lson);
    	else tr[rt].ls=tr[x].ls,insert(tr[x].rs,v,c,rson);
    }
    void dfs1(int x,int from)
    {
    	fa[x]=from,dep[x]=dep[from]+1,siz[x]=1;
    	insert(rot[from],a[x],val[a[x]],1,maxn,rot[x]);
    	for(int i=head[x];i!=-1;i=e[i].next)
    	{
    		int to1=e[i].to;
    		if(to1!=from)
    		{
    			dfs1(to1,x);
    			siz[x]+=siz[to1];
    			if(siz[to1]>siz[son[x]])son[x]=to1;
    		}
    	}
    }
    void dfs2(int x,int top)
    {
    	anc[x]=top;if(son[x])dfs2(son[x],top);
    	for(int i=head[x];i!=-1;i=e[i].next)
    	{
    		int to1=e[i].to;
    		if(to1!=fa[x]&&to1!=son[x])dfs2(to1,to1);
    	}
    }
    int get_lca(int x,int y)
    {
    	while(anc[x]!=anc[y])
    	{
    		if(dep[anc[x]]<dep[anc[y]])swap(x,y);
    		x=fa[anc[x]];
    	}
    	return dep[x]<dep[y]?x:y;
    }
    ll s[N];
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	for(int i=1;i<=200001;i++)val[i]=(ll)rand()*rand()*rand(),s[i]=s[i-1]^val[i];
    	while(T--)
    	{
    		memset(son,0,sizeof(son));memset(head,-1,sizeof(head));cnt=0;maxn=0;
    		scanf("%d%d",&n,&Q);
    		for(int i=1;i<=n;i++)scanf("%d",&a[i]),maxn=max(maxn,a[i]);
    		for(int i=1;i<n;i++)
    		{
    			int x,y;
    			scanf("%d%d",&x,&y);
    			add(x,y);add(y,x);
    		}
    		cnt=0;maxn++;
    		dfs1(1,0);dfs2(1,1);
    		while(Q--)
    		{
    			int x,y;scanf("%d%d",&x,&y);
    			int lca=get_lca(x,y),f=fa[lca];
    			x=rot[x],y=rot[y],lca=rot[lca],f=rot[f];
    			int l=1,r=maxn;
    			while(l<r)
    			{
    				int m=(l+r)>>1;
    				if((tr[tr[x].ls].sum^tr[tr[y].ls].sum^tr[tr[lca].ls].sum^tr[tr[f].ls].sum)==(s[m]^s[l-1]))
    				{
    					l=m+1,x=tr[x].rs,y=tr[y].rs,lca=tr[lca].rs,f=tr[f].rs;
    				}else
    				{
    					r=m,x=tr[x].ls,y=tr[y].ls,lca=tr[lca].ls,f=tr[f].ls;
    				}
    			}
    			printf("%d
    ",l);
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    goweb-goweb基础
    玩转Git
    程序爱好者的常用网站
    高等数学思维导图——6.微分方程
    前端趣玩——超炫的聚光灯效果
    Python课程笔记(四)
    高等数学思维导图——5.多元函数微分法及其应用
    算法很美(四)
    第五章——定积分必记公式
    十大经典排序算法
  • 原文地址:https://www.cnblogs.com/Winniechen/p/9118938.html
Copyright © 2011-2022 走看看