[SCOI2016]幸运数字

题解:

想找到树剖的题写写,然后就找到了这么一题

树剖+线段树+线性基显然

分析一下复杂度就上天了 $nlog^2*60^2$

不过树剖的log我忽略一下。。线性基合并肯定跑不满假设只有60.。

差不多还可以跑跑

于是就写了,然后竟然过了

#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for(int i=h;i<=t;i++)
#define dep(i,t,h) for(int i=t;i>=h;i--)
#define ll long long
#define me(x) memset(x,0,sizeof(x))
#define mep(x,y) memcpy(x,y,sizeof(y))
#define mid ((h+t)>>1)
namespace IO{
    char ss[1<<24],*A=ss,*B=ss;
    IL char gc()
    {
        return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++;
    }
    template<class T> void read(T &x)
    {
        rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48);
        while (c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f; 
    }
    char sr[1<<24],z[20]; int Z,C1=-1;
    template<class T>void wer(T x)
    {
        if (x<0) sr[++C1]='-',x=-x;
        while (z[++Z]=x%10+48,x/=10);
        while (sr[++C1]=z[Z],--Z);
    }
    IL void wer1()
    {
        sr[++C1]=' ';
    }
    IL void wer2()
    {
        sr[++C1]='\n';
    }
    template<class T>IL void maxa(T &x,T y) {if (x<y) x=y;}
    template<class T>IL void mina(T &x,T y) {if (x>y) x=y;} 
    template<class T>IL T MAX(T x,T y){return x>y?x:y;}
    template<class T>IL T MIN(T x,T y){return x<y?x:y;}
};
using namespace IO;
const int N=2.1e4;
const int N1=N*4;
ll v[N];
int head[N],l,dep[N],dy[N],son[N],dfn[N],cnt,num[N],fa[N];
int top[N],n,m,q;
struct re{
    int a,b;
}e[N*2];
IL void arr(int x,int y)
{
    e[++l].a=head[x];
    e[l].b=y;
    head[x]=l;
}
void dfs1(int x,int y)
{
    num[x]=1; dep[x]=dep[y]+1; fa[x]=y;
    for (rint u=head[x];u;u=e[u].a)
    {
        int v=e[u].b;
        if (v!=y)
        { 
          dfs1(v,x); num[x]+=num[v];
          if (num[v]>num[son[x]]) son[x]=v;
        }
    }
}
void dfs2(int x,int t,int y)
{
    top[x]=t; dfn[x]=++cnt; dy[cnt]=x;
    if (son[x]) dfs2(son[x],t,x);
    for (rint u=head[x];u;u=e[u].a)
    {
        int v=e[u].b;
        if (v!=y&&v!=son[x]) dfs2(v,v,x);
    }
}
struct re2{
    ll a[61];
    re2() {me(a);}
};
vector<re2> ve;
struct sgt{
    ll now[N1][61];
    IL re2 hb(ll *x,ll *y)
    {
        re2 ans;
        int cnt1=0,cnt2=0;
        rep(i,0,60) if (x[i]) cnt1++;
        rep(i,0,60) if (y[i]) cnt2++;
        if (cnt1>cnt2) swap(x,y);
        rep(i,0,60) ans.a[i]=y[i];
        rep(i,0,60)
          if (x[i])
          {
              ll k=x[i];
            dep(j,60,0)
            {
              if (!k) break;
              if ((k>>j)&1)
                if (ans.a[j]) k^=ans.a[j];
                else
                {
                    ans.a[j]=k; break;
                }
            }
          }
        return ans;
    }
    void build(int x,int h,int t)
    {
        if (h==t)
        {
            dep(i,60,0)
              if ((v[dy[h]]>>i)&1)
              {
                  now[x][i]=v[dy[h]];
                  break;
              }
            return;
        }
        build(x*2,h,mid); build(x*2+1,mid+1,t);
        re2 p=hb(now[x*2],now[x*2+1]);
        memcpy(now[x],p.a,sizeof(p.a));
    }
    void query(int x,int h,int t,int h1,int t1)
    {
        if (h1<=h&&t<=t1)
        {
            re2 p; memcpy(p.a,now[x],sizeof(now[x]));
            ve.push_back(p);
            return;
        }
        if (h1<=mid) query(x*2,h,mid,h1,t1);
        if (mid<t1) query(x*2+1,mid+1,t,h1,t1);
    }
    ll query2(int x,int y)
    {
        ve.clear();
        int f1=top[x],f2=top[y];
        while (f1!=f2)
        {
            if (dep[f1]<dep[f2]) swap(f1,f2),swap(x,y);
            query(1,1,n,dfn[f1],dfn[x]);
            x=fa[f1]; f1=top[x];
        }
        if (dep[x]<dep[y]) swap(x,y);
        query(1,1,n,dfn[y],dfn[x]);
        int l=(int)(ve.size())-1;
        re2 p;
        rep(i,0,l) p=hb(p.a,ve[i].a);
        ll now=0;
        dep(i,60,0)
          if (p.a[i]&&!((now>>i)&1))
          {
              now^=p.a[i];
          }
        return now;
    }
}S;
int main()
{
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    read(n); read(q);
    rep(i,1,n) read(v[i]);
    rep(i,1,n-1)
    {
        int x,y;
        read(x); read(y);
        arr(x,y); arr(y,x);
    }
    dfs1(1,0); dfs2(1,1,0);
    S.build(1,1,n);
    rep(i,1,q)
    {
        int x,y;
        read(x); read(y);
        wer(S.query2(x,y)); wer2();
    }
    fwrite(sr,1,C1+1,stdout);
    return 0;
}

当然感觉是数据并不强的原因。。

然而这题用倍增+线性基$nlog^3$的复杂度 也就比树剖快了一倍

线性基合并可以有点常数优化见我的代码 看下面

当然这题是有$nlog^2n$的做法的

既然离线我们利用点分治

然后把lca等于rt的放在现在计算

点分治的一个常数优化是对n<=k的时候进行暴力计算

但这题里效果应该并不明显

另外上面那个线性基合并写的太菜了。。

现在的这个比那个少算了100倍???(实测一个线性基循环3e7 一个1e5)

优化1:为0直接跳

优化2:从当前位往下

优化3:维护最低位

也就是说线性基合并基本没花时间。。 时间在于插入线性基

然后把插入线性基也这么优化一下

 

#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for (int i=h;i<=t;i++)
#define dep(i,t,h) for (int i=t;i>=h;i--)
#define me(x) memset(x,0,sizeof(x))
#define ll long long
#define mep(x,y) memcpy(x,y,sizeof(y))
namespace IO{
    char ss[1<<24],*A=ss,*B=ss;
    IL char gc()
    {
        return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++;
    }
    template<class T>void read(T &x)
    {
        rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48);
        while (c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f;
    }
    char sr[1<<24],z[20]; int Z,C=-1;
    template<class T>void wer(T x)
    {
        if (x<0) sr[++C]='-',x=-x;
        while (z[++Z]=x%10+48,x/=10);
        while (sr[++C]=z[Z],--Z);
    }
    IL void wer1() { sr[++C]=' ';}
    IL void wer2() { sr[++C]='\n';}
    template<class T>IL void maxa(T &x,T y) { if (x<y) x=y;} 
    template<class T>IL void mina(T &x,T y) { if (x>y) x=y;}
    template<class T>IL T MAX(T x,T y) {return x>y?x:y;}
    template<class T>IL T MIN(T x,T y) {return x<y?x:y;}
};
using namespace IO;
const int N=3e5;
bool vis[N];
int head[N],l,num[N],f[N],rt,col[N],all,pos[N],jl[N];
ll now[N][61],p[N][61],ans[N],v[N];
struct re{
    int a,b,c;
}e[N*2],a[N];
vector<re>ve[N];
IL void arr(int x,int y)
{
    e[++l].a=head[x];
    e[l].b=y;
    head[x]=l;
}
struct re2{
    ll a[61];
    re2() {me(a);}
};
int cnt2=0,cnt3=0; 
IL re2 hb(ll *x,ll *y)
{
        cnt2++; 
        re2 ans;
        rep(i,0,60)
        {   
          if (y[i]) ans.a[i]=y[i]; else ans.a[i]=x[i];
        }
        int A;
        for(A=0;A<=60;A++) if (!ans.a[A]) break;
        rep(i,0,60)
          if (x[i]&&y[i])
          {
              ll k=x[i];
            dep(j,i,A)
            {
                cnt3++;
                if (!k) break;
                if ((k>>j)&1)
                if (ans.a[j]) k^=ans.a[j];
                else
                {
                    ans.a[j]=k; break;
                }
                if (j==A)
                {
                    for (;A<=60;A++) if (!ans.a[A]) break;
                }
            }
          } 
        return ans;
}
void fdr(int x,int y)
{
    num[x]=1; f[x]=0;
    for (rint u=head[x];u;u=e[u].a)
    {
        int v=e[u].b;
        if (v!=y&&!vis[v])
        {
            fdr(v,x); num[x]+=num[v];
            if (num[v]>f[x]) f[x]=num[v]; 
        }
    }
    if (all-num[x]>f[x]) f[x]=all-num[x];
    if (f[x]<f[rt]) rt=x;
}
IL void ins(ll *x,ll y,int z,int &k)
{
    dep(i,z,k)
    {
      if (!y) return;
      if ((y>>i)&1)
        if (x[i]) y^=x[i]; else
        {
            x[i]=y; break;
        }
    }
    while (x[k]) k++;
}
void dfs(int x,int y,int color)
{
    mep(p[x],p[y]); jl[x]=jl[y];
    ins(p[x],v[x],pos[x],jl[x]);
    col[x]=color;
    for (rint u=head[x];u;u=e[u].a)
    {
        int v=e[u].b;
        if (v!=y&&!vis[v]) dfs(v,x,color);
    }
}
int cnt=0;
void dfz(int x,int y)
{
    all=num[x]; rt=0; f[x]=0; fdr(x,0);
    mep(p[rt],now[rt]); jl[rt]=0;
    for(rint u=head[rt];u;u=e[u].a)
    {
        int v=e[u].b;
        if (!vis[v]) dfs(v,rt,++cnt);
    }
    int l=(int)(ve[y].size())-1;
    rep(i,0,l)
    {
      int x1=ve[y][i].a,x2=ve[y][i].b;
      if (col[x1]!=col[x2]||x1==rt)
      {
          re2 o=hb(p[x1],p[x2]);
          ll now=0;
        dep(i,60,0)
          if (o.a[i]&&!((now>>i)&1))
          {
              now^=o.a[i];
          }
        ans[ve[y][i].c]=now;
      } else ve[col[x1]].push_back(ve[y][i]);
    }
    vis[rt]=1;
    for (rint u=head[rt];u;u=e[u].a)
    {
        int v=e[u].b;
        if (!vis[v]) dfz(v,col[v]);
    }
}
int main()
{
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    f[0]=1e9; 
    int n,m;
    read(n); read(m);
    rep(i,1,n)
    { 
      read(v[i]);
      dep(j,60,0)
        if ((v[i]>>j)&1)
        {
            now[i][j]=v[i]; pos[i]=j; break;
        }
    }
    rep(i,1,n-1)
    {
        int x,y;
        read(x); read(y);
        arr(x,y); arr(y,x); 
    }
    rep(i,1,m)
    { 
      read(a[i].a),read(a[i].b),a[i].c=i;
      ve[1].push_back(a[i]); 
    }
    num[1]=n; 
    cnt=1; dfz(1,1);
    rep(i,1,m) wer(ans[i]),wer2();
    fwrite(sr,1,C+1,stdout);
    return 0;
}

 

posted @ 2018-12-11 18:04  尹吴潇  阅读(273)  评论(0编辑  收藏  举报