zoukankan      html  css  js  c++  java
  • [bzoj5338]xor

    维护两颗可持久化字典树(当然可以放在一起),第一棵维护每一个点到根的每一位的二进制数量,在其父亲的基础上建立;第二棵维护dfs序上每一个点到第1个点的二进制数量,在其上一个点的基础上建立。

    对于询问1,在第二棵上询问该子树对应区间;对于询问2,拆成x~lcalca~y两段询问,询问时直接贪心即可。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define s(k,p) tr[k].son[p]
     4 #define zt s(k1,p),s(k2,p),x,y-1
     5 #define P ((x&(1<<y))>0)
     6 #define N 100005
     7 struct ji{
     8     int nex,to;
     9 }edge[N<<1];
    10 struct ji2{
    11     int sum,son[2];
    12 }tr[80*N];
    13 int V,E,n,q,p,x,y,z,sz[N],head[N],r[N<<1],in[N],out[N],f[N][21],a[N],id[N];
    14 void add(int x,int y){
    15     edge[E].nex=head[x];
    16     edge[E].to=y;
    17     head[x]=E++;
    18 }
    19 bool pd(int x,int y){
    20     return (in[x]<=in[y])&&(out[y]<=out[x]);
    21 }
    22 int lca(int x,int y){
    23     if (pd(x,y))return x;
    24     for(int i=20;i>=0;i--)
    25         if (!pd(f[x][i],y))x=f[x][i];
    26     return f[x][0];
    27 }
    28 void ins(int k1,int &k2,int x,int y){
    29     tr[k2=++V]=tr[k1];
    30     tr[k2].sum++;
    31     if (y<0)return;
    32     bool p=P;
    33     ins(zt);
    34 }
    35 int query(int k1,int k2,int x,int y){
    36     if (y<0)return 0;
    37     bool p=(tr[s(k1,P^1)].sum<tr[s(k2,P^1)].sum)^P;
    38     return (P^p)*(1<<y)+query(zt);
    39 }
    40 int dfs(int k,int fa){
    41     ins(r[fa],r[k],a[k],30);
    42     f[k][0]=fa;
    43     in[k]=++x;
    44     id[x]=k;
    45     sz[k]=1;
    46     for(int i=1;i<=20;i++)f[k][i]=f[f[k][i-1]][i-1];
    47     for(int i=head[k];i!=-1;i=edge[i].nex)
    48         if (edge[i].to!=fa)sz[k]+=dfs(edge[i].to,k);
    49     out[k]=x;
    50     return sz[k];
    51 }
    52 int main(){
    53     scanf("%d%d",&n,&q);
    54     memset(head,-1,sizeof(head));
    55     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    56     for(int i=1;i<n;i++){
    57         scanf("%d%d",&x,&y);
    58         add(x,y);
    59         add(y,x);
    60     }
    61     x=0;
    62     dfs(1,1);
    63     f[1][0]=0;
    64     for(int i=1;i<=n;i++)ins(r[i+n],r[i+n+1],a[id[i]],30);
    65     for(int i=1;i<=q;i++){
    66         scanf("%d%d%d",&p,&x,&y);
    67         if (p==1)printf("%d\n",query(r[in[x]+n],r[in[x]+sz[x]+n],y,30));
    68         else{
    69             scanf("%d",&z);
    70             p=f[lca(x,y)][0];
    71             printf("%d\n",max(query(r[p],r[x],z,30),query(r[p],r[y],z,30)));
    72         }
    73     }
    74 }
    View Code
  • 相关阅读:
    【Selenium-WebDriver问题点】chromeDriver和chrome浏览器版本之间的兼容性问题
    【Linux】【Jmeter】配置Jmeter服务器和运行Jmeter
    【Linux】【JDK】常用命令使用集和裸机配置JDK步骤。
    【Linux】使用ZStack私有云创建本地Linux服务器
    js基本数据类型和typeof
    Javascript 面向对象编程
    css3作3D旋转视频展示
    css3中的border-radius
    css3中做3D导航栏
    css3动画学习笔记
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11249952.html
Copyright © 2011-2022 走看看