[bzoj4763]雪辉&[bzoj4812][Ynoi2017]由乃打扑克

来自FallDream的博客,未经允许,请勿转载,谢谢。


cut掉部分题面。

给一个n个点的树,点有点权,有m次询问,每次询问多条链的并有多少种不同的点权以及它的mex
mex就是一个集合中最小的没有出现的非负整数,注意0要算
比如说集合是1,9,2,6,0,8,1,7,则出现了0,1,2,6,7,8,9这7种不同的点权,因为没有3所以mex是3
n<=100000,总共询问的链数量<=100000 权值<=30000
 
考虑对树分块,预处理每个块的中心到它父亲中同样是中心的点的bitset,然后查询的时候先暴力跳到中心,再能跳到上一个中心就跳,最后再暴力跳即可。
手写bitset来查询答案。
预处理复杂度$n\sqrt{n}$,每次询问复杂度是$O(\sqrt{n}+\frac{30000}{64})$
 
另一道由乃打扑克也是同样的做法,最后询问的时候,16位可以一起处理,预处理0-65535里面每个数低位连续的1的数量,中间的1在不同幂次下的贡献和高位连续的1的数量。
雪辉
#include<iostream>
#include<cstdio>
#define MN 100000
#define MB 320
#define MD 17
#define ull unsigned long long
#define getchar() (*S++)
char B[1<<26],*S=B;
using namespace std;
inline int read()
{
    int x = 0 , f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}
int n,m,flag,w[MN+5],head[MN+5],cnt=0,fa[MD+5][MN+5],mx[MN+5];
int mark[MN+5],dep[MN+5],rt[MB+5],rtnum=0,top[MN+5],Num[MN+5];
struct edge{int to,next;}e[MN*2+5];
ull MAXN=0;
struct Bitset
{
    ull s[470];int len;
    void Clear(){for(int i=0;i<470;++i) s[i]=0;len=0;}
    void operator |=(int x){s[x>>6]|=1LL<<(x&63);len=max(len,x>>6);}
    void operator |=(const Bitset&y)
    {
        len=max(len,y.len);
        for(int i=0;i<=len;++i)
            s[i]|=y.s[i];
    }
    int num()
    {
        int res=0;
        for(int i=0;i<=len;++i)
            res+=Num[s[i]>>48]+Num[(s[i]>>32)&65535]+Num[(s[i]>>16)&65535]+Num[s[i]&65535];
        return res;
    }
    int Query()
    {
        for(int i=0;i<470;++i) if(s[i]!=MAXN)
            for(int j=0;j<64;++j)
                if(!(s[i]&((ull)1<<j)))
                    return i*64+j;
    }
}b[MB+5][MB+5],ans;

inline void ins(int f,int t)
{
    e[++cnt]=(edge){t,head[f]};head[f]=cnt;
    e[++cnt]=(edge){f,head[t]};head[t]=cnt;
}

void init(int x)
{
    mx[x]=dep[x];
    for(int i=head[x];i;i=e[i].next)
        if(e[i].to!=fa[0][x])
        {
            fa[0][e[i].to]=x;
            dep[e[i].to]=dep[x]+1;
            init(e[i].to);
            mx[x]=max(mx[x],mx[e[i].to]);
        }
    if(mx[x]-dep[x]>=MB||x==1) mx[x]=0,rt[mark[x]=++rtnum]=x;
}

inline int lca(int x,int y)
{
    if(dep[x]<dep[y]) swap(x,y);
    for(int k=dep[x]-dep[y],j=0;k;k>>=1,++j)
        if(k&1) x=fa[j][x];
    if(x==y) return x;
    for(int i=MD;~i;--i)
        if(fa[i][x]!=fa[i][y])
            x=fa[i][x],y=fa[i][y];
    return fa[0][x];
}
int last=0;
int main()
{
    fread(B,1,1<<26,stdin);
    n=read();m=read();flag=read();
    for(int i=0;i<64;++i) MAXN|=(ull)1<<i;
    for(int i=0;i<=65536;++i)
        for(int j=i;j;j>>=1)
            Num[i]+=(j&1);
    for(int i=1;i<=n;++i) w[i]=read();
    for(int i=1;i<n;++i) ins(read(),read());
    dep[1]=1;init(1);
    for(int i=1;i<=MD;++i)
        for(int j=1;j<=n;++j)
            fa[i][j]=fa[i-1][fa[i-1][j]];
    for(int i=1;i<=rtnum;++i)
    {
        Bitset now;now.Clear();now|=w[rt[i]];b[i][i]=now;
        for(int k=fa[0][rt[i]];k;k=fa[0][k])
        {
            now|=w[k];
            if(mark[k])
            {
                b[i][mark[k]]=now;
                if(!top[rt[i]]) top[rt[i]]=k;
            }
        }
    }
    for(int i=1;i<=m;++i)
    {
        ans.Clear();int nn=read();
        for(int j=1;j<=nn;++j)
        {
            int x=read(),y=read(),xx,yy;
            if(flag) x^=last,y^=last;
            int z=lca(x,y);ans|=w[x];ans|=w[y];
            for(;!mark[x]&&dep[x]>dep[z];)
                x=fa[0][x],ans|=w[x];
            for(;!mark[y]&&dep[y]>dep[z];)
                y=fa[0][y],ans|=w[y];
            for(xx=x;dep[top[xx]]>=dep[z];xx=top[xx]);
            for(yy=y;dep[top[yy]]>=dep[z];yy=top[yy]);
            ans|=b[mark[x]][mark[xx]];
            ans|=b[mark[y]][mark[yy]];
            for(;xx!=yy;)
            {
                if(dep[xx]<dep[yy]) swap(xx,yy);
                xx=fa[0][xx];ans|=w[xx];
            }
        }
        int x=ans.num(),y=ans.Query();
        last=x+y;
        printf("%d %d\n",x,y);
    }
    return 0;
}
View Code

由乃打扑克

#include<iostream>
#include<cstdio>
#define MN 100000
#define MB 350
#define MD 17
#define int unsigned int
#define uint  int
#define ull unsigned long long
#define getchar() (*S++)
char B[1<<26],*S=B;
using namespace std;
inline long long read()
{
    long long x = 0 , f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}
int n,m,w[MN+5],head[MN+5],cnt=0,fa[MD+5][MN+5],mx[MN+5];
int mark[MN+5],dep[MN+5],rt[MB+5],rtnum=0,top[MN+5],front[MN+5],back[MN+5];
uint pw[30005][32],Num[65536][32],K,last=0;
struct edge{int to,next;}e[MN*2+5];

void Combine(uint&ans,uint&len,int x)
{
    if(x==65535) {len+=16;return;}
    len+=front[x];ans+=pw[len][K];
    ans+=Num[x][K];len=back[x];
}
struct Bitset
{
    ull s[470];int len;
    void Clear(){for(int i=0;i<470;++i) s[i]=0;len=0;}
    void operator |=(int x){s[x>>6]|=1LL<<(x&63);len=max(len,x>>6);}
    void operator |=(const Bitset&y)
    {
        len=max(len,y.len);
        for(int i=0;i<=len;++i)
            s[i]|=y.s[i];
    }
    uint Query(int k)
    {
        uint ans=0,L=0;
        for(int i=0;i<=len;++i)
            Combine(ans,L,s[i]&65535),
            Combine(ans,L,(s[i]>>16)&65535),
            Combine(ans,L,(s[i]>>32)&65535),
            Combine(ans,L,(s[i]>>48)&65535);
        return (ans+=pw[L][k]);
    }
}b[MB+5][MB+5],ans;

inline void ins(int f,int t)
{
    e[++cnt]=(edge){t,head[f]};head[f]=cnt;
    e[++cnt]=(edge){f,head[t]};head[t]=cnt;
}

void init(int x)
{
    mx[x]=dep[x];
    for(int i=head[x];i;i=e[i].next)
        if(e[i].to!=fa[0][x])
        {
            fa[0][e[i].to]=x;
            dep[e[i].to]=dep[x]+1;
            init(e[i].to);
            mx[x]=max(mx[x],mx[e[i].to]);
        }
    if(mx[x]-dep[x]>=MB||x==1) mx[x]=0,rt[mark[x]=++rtnum]=x;
}

inline int lca(int x,int y)
{
    if(dep[x]<dep[y]) swap(x,y);
    for(int k=dep[x]-dep[y],j=0;k;k>>=1,++j)
        if(k&1) x=fa[j][x];
    if(x==y) return x;
    for(int i=MD;~i;--i)
        if(fa[i][x]!=fa[i][y])
            x=fa[i][x],y=fa[i][y];
    return fa[0][x];
}

main()
{
    fread(B,1,1<<26,stdin);
    n=read();m=read();
    for(int i=1;i<=30000;++i)
    {
        int k=1;pw[i][0]=1;
        for(int j=1;j<=30;++j)
            pw[i][j]=(k*=i);
    }
    
    for(int i=0;i<=65534;++i)
    {
        int j=0,flag=0;
        for(int k=i,kk=1;kk<=16;++kk,k>>=1)
            if(k&1) ++j;
            else
            {
                if(!flag) flag=1,front[i]=j;
                else for(int kkk=0;kkk<=30;++kkk)
                    Num[i][kkk]+=pw[j][kkk];
                j=0;
            }
        back[i]=j;
    }
    for(int i=1;i<=n;++i) w[i]=read();
    for(int i=1;i<n;++i) ins(read(),read());
    dep[1]=1;init(1);
    for(int i=1;i<=MD;++i)
        for(int j=1;j<=n;++j)
            fa[i][j]=fa[i-1][fa[i-1][j]];
    for(int i=1;i<=rtnum;++i)
    {
        Bitset now;now.Clear();now|=w[rt[i]];b[i][i]=now;
        for(int k=fa[0][rt[i]];k;k=fa[0][k])
        {
            now|=w[k];
            if(mark[k])
            {
                b[i][mark[k]]=now;
                if(!top[rt[i]]) top[rt[i]]=k;
            }
        }
    }
    for(int i=1;i<=m;++i)
    {
        ans.Clear();int nn=read();
        for(int j=1;j<=nn;++j)
        {
            uint x=(read()^last),y=(read()^last),xx,yy;
            uint z=lca(x,y);ans|=w[x];ans|=w[y];
            if(x<1||x>n||y<1||y>n) return 0;
            for(;!mark[x]&&dep[x]>dep[z];)
                x=fa[0][x],ans|=w[x];
            for(;!mark[y]&&dep[y]>dep[z];)
                y=fa[0][y],ans|=w[y];
            for(xx=x;dep[top[xx]]>=dep[z];xx=top[xx]);
            for(yy=y;dep[top[yy]]>=dep[z];yy=top[yy]);
            ans|=b[mark[x]][mark[xx]];
            ans|=b[mark[y]][mark[yy]];
            for(;xx!=yy;)
            {
                if(dep[xx]<dep[yy]) swap(xx,yy);
                xx=fa[0][xx];ans|=w[xx];
            }
        }
        printf("%u\n",last=ans.Query(K=read()));
    }
    return 0;
}
View Code
posted @ 2017-05-30 22:35  FallDream  阅读(1656)  评论(0编辑  收藏  举报