• bzoj 4763: 雪辉


    Description

    给一个n个点的树,点有点权,有m次询问,每次询问多条链的并有多少种不同的点权以及它的mex
    mex就是一个集合中最小的没有出现的非负整数,注意0要算
    比如说集合是1,9,2,6,0,8,1,7,则出现了0,1,2,6,7,8,9这7种不同的点权,因为没有3所以mex是3

    Solution

    暴力做法是枚举把点对 ((x,y)) 往上跳,用桶记录一下答案
    我们想办法把往上跳的过程分块优化,于是随机 (sqrt{n}) 个点作为关键点
    预处理出每一个关键点往上跳到的第一个关键点和到往上的每一个关键点的桶
    这样询问就可以先暴力找到第一个关键点,然后从关键点开始每次跳到下一个关键点,再从最后一个跳到 (lca),跳的次数期望是 (sqrt{n})
    这个桶用 (bitset) 代替,就可以 (O(frac{30000}{32})) 的合并的了
    由于要找 (mex) 所以要手写
    关于区间 (mex) 判断每一个数字是否是满的,如果不满,则暴力扫这个数字的每一位
    (count) 函数也可以预处理出每一个数字的 (1) 的个数
    这样 (mex,count) 的复杂度都是 (O(frac{30000}{32}))

    #include<bits/stdc++.h>
    using namespace std;
    template<class T>void gi(T &x){
    	int f;char c;
    	for(f=1,c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
    	for(x=0;c<='9'&&c>='0';c=getchar())x=x*10+(c&15);x*=f;
    }
    const int N=1e5+10,B=320;
    int n,Q,m,T,a[N],head[N],nxt[N*2],to[N*2],num=0,p[N],dep[N];
    bool imp[N];int fa[N][18],t[N],id[N],top[N],mx=0;
    inline void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;}
    bitset<30001>f[B+1][B+1],g,ans;//B*B*30000*4/1024/1024
    inline void dfs(int x){
    	for(int i=1;i<=17;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
    	for(int i=head[x],u;i;i=nxt[i]){
    		if(dep[u=to[i]])continue;
    		dep[u]=dep[x]+1;fa[u][0]=x;dfs(u);
    	}
    }
    inline int lca(int x,int y){
    	if(dep[x]<dep[y])swap(x,y);
    	for(int i=17;i>=0;i--)if((dep[x]-dep[y])>>i&1)x=fa[x][i];
    	if(x==y)return x;
    	for(int i=17;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
    	return fa[x][0];
    }
    inline void solve(int u){
    	int x=p[u];g.reset();
    	while(x){
    		g.set(a[x]);
    		if(imp[x]){
    			f[u][id[x]]=g;
    			if(x!=p[u] && !top[p[u]])top[p[u]]=x;
    		}
    		x=fa[x][0];
    	}
    }
    inline int getmex(){
    	for(int i=0;i<=mx;i++)if(!ans[i])return i;
    	return mx+1;
    }
    int main(){
      freopen("pp.in","r",stdin);
      freopen("pp.out","w",stdout);
      //cout<<(sizeof(f)+sizeof(pre))/1000/1000<<endl;
      srand(19260817);
      int x,y,k,z,lastans=0;
      cin>>n>>Q>>T;
      for(int i=1;i<=n;i++)gi(a[i]),mx=max(mx,a[i]);
      for(int i=1;i<n;i++){
    	  gi(x);gi(y);
    	  link(x,y);link(y,x);
      }
      for(int i=1;i<=n;i++)p[i]=i;
      random_shuffle(p+1,p+n+1);
      for(int i=(m=min(B,n));i>=1;i--)imp[p[i]]=1,id[p[i]]=i;
      dep[1]=1;dfs(1);
      for(int i=1;i<=m;i++)solve(i);
      while(Q--){
    	  gi(k);ans.reset();
    	  while(k--){
    		  gi(x);gi(y);x^=(lastans*T);y^=(lastans*T);
    		  z=lca(x,y);ans.set(a[z]);
    		  
    		  while(x!=z && !imp[x])ans.set(a[x]),x=fa[x][0];
    		  int last=id[x];
    		  while(imp[x] && dep[top[x]]>=dep[z])x=top[x];
    		  ans|=f[last][id[x]];
    		  while(x!=z)ans.set(a[x]),x=fa[x][0];
    
    		  while(y!=z && !imp[y])ans.set(a[y]),y=fa[y][0];
    		  last=id[y];
    		  while(imp[y] && dep[top[y]]>=dep[z])y=top[y];
    		  ans|=f[last][id[y]];
    		  while(y!=z)ans.set(a[y]),y=fa[y][0];
    	  }
    	  int t1=ans.count(),t2=getmex();lastans=t1+t2;
    	  printf("%d %d
    ",t1,t2);
      }
      return 0;
    }
    
    
  • 相关阅读:
    ASM instance正常启动,但是用sqlplus 连不上的问题
    Ubuntu环境下,项目出现:Call to undefined function curl_init() 提示
    linux安装curl扩展
    https请求排错过程
    php-fpm.conf文件的位置在哪里
    如何查找php-fpm监听的端口
    laravel AppKernel.php中的middleware、middlewareGroups、routeMiddleware
    laravel项目数据库交互逻辑
    Laravel中APP_KEY起什么作用
    php 出现Warning: A non-numeric value encountered问题的原因及解决方法
  • 原文地址:https://www.cnblogs.com/Yuzao/p/9092175.html
Copyright © 2020-2023  润新知