zoukankan      html  css  js  c++  java
  • [luogu3292]幸运数字

    考虑点分治,将询问离线后计算重心到每一个点的线性基,然后再询问重心到每一个点的线性基,时间复杂度为$o(3600q)$,可以过(然而太菜的我写了倍增维护线性基,震惊于倍增和线性基常数之小)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 20005
     4 #define oo 0x3f3f3f3f
     5 #define ll long long
     6 struct ji{
     7     ll a[61];
     8 }o,dp[N][21];
     9 struct ji2{
    10     int nex,to;
    11 }edge[N<<1];
    12 int E,n,m,x,y,head[N],in[N],out[N],f[N][21];
    13 ll a[N];
    14 bool pd(int x,int y){
    15     return (in[x]<=in[y])&&(out[y]<=out[x]);
    16 }
    17 void add(int x,int y){
    18     edge[E].nex=head[x];
    19     edge[E].to=y;
    20     head[x]=E++;
    21 }
    22 void add(ji &x,ll y){
    23     for(int i=60;i>=0;i--)
    24         if (y&(1LL<<i))
    25             if (x.a[i])y^=x.a[i];
    26             else{
    27                 x.a[i]=y;
    28                 break;
    29             }
    30 }
    31 void merge(ji &x,ji y){
    32     for(int i=0;i<=60;i++)
    33         if (y.a[i])add(x,y.a[i]);
    34 }
    35 void dfs(int k,int fa){
    36     in[k]=++x;
    37     f[k][0]=fa;
    38     add(dp[k][0],a[k]);
    39     for(int i=1;i<=20;i++){
    40         f[k][i]=f[f[k][i-1]][i-1]; 
    41         dp[k][i]=dp[k][i-1];
    42         merge(dp[k][i],dp[f[k][i-1]][i-1]);
    43     }
    44     for(int i=head[k];i!=-1;i=edge[i].nex)
    45         if (edge[i].to!=fa)dfs(edge[i].to,k);
    46     out[k]=++x;
    47 }
    48 ji calc(int x,int y){
    49     if (x==y)return dp[x][0];
    50     ji z;
    51     memset(z.a,0,sizeof(z.a));
    52     for(int i=20;i>=0;i--)
    53         if (!pd(f[x][i],y)){
    54             merge(z,dp[x][i]);
    55             x=f[x][i];
    56         }
    57     for(int i=20;i>=0;i--)
    58         if (!pd(f[y][i],x)){
    59             merge(z,dp[y][i]);
    60             y=f[y][i];
    61         }
    62     merge(z,dp[x][pd(x,y)^1]);
    63     if (!pd(y,x))merge(z,dp[y][0]);
    64     return z;
    65 }
    66 ll query(ji o){
    67     ll ans=0;
    68     for(int j=60;j>=0;j--)
    69         if ((ans&(1LL<<j))==0)ans^=o.a[j];
    70     return ans;
    71 }
    72 int main(){
    73     scanf("%d%d",&n,&m);
    74     memset(head,-1,sizeof(head));
    75     for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    76     for(int i=1;i<n;i++){
    77         scanf("%d%d",&x,&y);
    78         add(x,y);
    79         add(y,x);
    80     }
    81     dfs(1,1);
    82     for(int i=1;i<=m;i++){
    83         scanf("%d%d",&x,&y);
    84         printf("%lld\n",query(calc(x,y)));
    85     }
    86 }
    View Code
  • 相关阅读:
    iOS中NSArray的过滤
    Android SurfaceView 的应用
    让你的模拟器不再卡:VirtualBox安裝 Androidx86 4.0
    SurfaceView 绘图覆盖刷新及脏矩形刷新方法
    ios iphone开发内存管理
    IOS上的socket通信
    【转载】反射之实例创建ConstructorInfo.Invoke 对比 Activator.CreateInstance
    cookie 和session 的区别详解
    LPC2132 调试记 (转)
    三极管开关电路基础
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11330369.html
Copyright © 2011-2022 走看看