1 条题解

  • 0
    @ 2025-8-24 21:55:27

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 消失的海岸线
    **

    搬运于2025-08-24 21:55:27,当前版本为作者最后更新于2018-01-12 21:56:58,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    丢个博客链接。。

    这题打 LOJ 的 VP 的时候写暴力+卡常拿了 83分...

    其实 YY 出做法是不困难的,考虑维护深度模 KK 意义下相同的节点,建 KK 颗树即可。

    kk 较大的时候暴力跳,否则 dfsdfs 序+树状数组统计。

    对于修改操作,用并查集将都是 11 的串起来即可,开方 loglog 次就变成 11 了,和花神游历各国那题是一样的。

    然后就没了...

    结果巨不好写...

    不要问我复杂度分析和块大小多大比较优...详细一点的可以看官方题解,贴个代码(逃

        #include <cmath>
        #include <queue>
        #include <cstdio>
        #include <iomanip>
        #include <cstdlib>
        #include <cstring>
        #include <iostream>
        #include <algorithm>
        #define N 50010
        #define MX 500000
        #define ll long long
        using namespace std;
        #define fstc __attribute__((optimize("-O3")))
        #define IL __inline__ __attribute__((always_inline))
        char xB[1<<15],*xS=xB,*xT=xB;
        #define getchar() (xS==xT&&(xT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xT)?0:*xS++)
        fstc IL ll read()
        {
            ll 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;
        }
        #define OUT 2000000
        char Out[OUT],*ou=Out;
        int Outn[30],Outcnt;
        fstc IL void write(ll x)
        {
            if(!x)*ou++=48;
            else
            {
                for(Outcnt=0;x;x/=10)Outn[++Outcnt]=x%10+48;
                while(Outcnt)*ou++=Outn[Outcnt--];
            }
        }
        #define K 20
        int n,Q;
        int path[N],path_top;
        ll a[N];
        int sqr[MX+10];
        struct graph
        {
            struct zgz
            {
                int next,to;
            }edge[N<<1];
            int head[N],cnt;
            fstc void init(){cnt=1;}
            fstc void add(int from,int to)
            {
                edge[cnt].to=to;
                edge[cnt].next=head[from];
                head[from]=cnt++;
            }
            fstc void ins(int from,int to)
            {add(from,to),add(to,from);}
        };
        struct Bit
        {
            int n;
            ll c[N<<1];
            fstc void add(int x,ll v)
            {
                for(;x<=n;x+=x&(-x))
                c[x]+=v;
            }
            fstc ll ask(int x)
            {
                ll ret=0;
                for(;x;x-=x&(-x))
                ret+=c[x];
                return ret;
            }
        };
        struct Unionset
        {
            int n;
            int fa[N];
            fstc void init(int x)
            {
                n=x;
                for(int i=1;i<=n;i++)fa[i]=i;
            }
            fstc int find(int x)
            {return fa[x]==x?x:fa[x]=find(fa[x]);}
            fstc void Union(int x,int y)
            {if(find(x)!=find(y))fa[fa[x]]=y;}
        };
        struct block
        {
            graph G;
            Unionset S;
            Bit B;
            int fa[N],deep[N];
            fstc void set_fa(int x,int f)
            {fa[x]=f,G.add(f,x);}
            int tim_in[N],tim_out[N],dfn;
            fstc void dfs(int x)
            {
                tim_in[x]=++dfn;
                B.add(dfn,a[x]);
                for(int i=G.head[x];i;i=G.edge[i].next)
                {
                    int to=G.edge[i].to;
                    deep[to]=deep[x]+1;
                    dfs(to);
                }
                tim_out[x]=++dfn;
                B.add(dfn,-a[x]);
            }
            fstc void init()
            {
                S.init(n);
                for(int i=1;i<=n;i++)
                if(a[i]==1) S.Union(i,fa[i]);
                B.n=n<<1;
                for(int i=1;i<=n;i++)
                if(!fa[i])deep[i]=1,dfs(i);
            }
            fstc void modify(int x,ll v)
            {
                B.add(tim_in[x],v-a[x]),B.add(tim_out[x],a[x]-v);
                if(v==1)S.Union(x,fa[x]);
            }
            fstc void get_path(int x,int pos)
            {
                while(deep[x]>=deep[pos])
                {
                    path[++path_top]=x;
                    x=S.find(fa[x]);
                }
            }
            fstc ll ask(int x,int top)
            {return B.ask(tim_in[x])-B.ask(tim_in[fa[top]]);}
        }T[K+5];
        graph G;
        int fa[N],deep[N];
        int stk[N],top;
        int anc[N][17];
        fstc void dfs(int x)
        {
            stk[++top]=x;
            for(int i=1;i<=K&&i<top;i++)
            T[i].set_fa(x,stk[top-i]);
            for(int i=G.head[x];i;i=G.edge[i].next)
            {
                int to=G.edge[i].to;
                if(to==fa[x])continue ;
                fa[to]=x,deep[to]=deep[x]+1;
                dfs(to);
            }
            top--;
        }
        fstc void init()
        {
            for(int i=1;i<=K;i++)T[i].G.init();
            for(int i=1;i<=n-1;i++)
            {
                int x=read(),y=read();
                G.ins(x,y);
            }
            deep[1]=1;
            dfs(1);
            for(int i=1;i<=K;i++) T[i].init();
            for(int i=1;i<=n;i++) anc[i][0]=fa[i];
            for(int j=1;j<=16;j++)
            for(int i=1;i<=n;i++) anc[i][j]=anc[anc[i][j-1]][j-1];
        }
        fstc int jump(int x,int step)
        {
            for(int i=0;i<=16;i++)if((step&(1<<i))>0)x=anc[x][i];
            return x;
        }
        fstc void modify(int x)
        {
            if(a[x]==1) return ;
            ll pos;
            if(a[x]<=MX) pos=sqr[a[x]];
            else pos=sqrt(a[x]);
            for(int i=1;i<=K;i++)T[i].modify(x,pos);
            a[x]=pos;
        }
        fstc ll ask(int x,int pos,int step)
        {
            ll ret=0;
            while(deep[x]>deep[pos])
                ret+=a[x],x=jump(x,step);
            return ret;
        }
        fstc void get_path(int x,int pos,int step)
        {
            while(x!=pos)
            {
                if(a[x]>1)path[++path_top]=x;
                x=jump(x,step);
            }
            if(a[pos]>1)path[++path_top]=pos;
        }
        fstc int get_lca(int x,int y)
        {
            if(deep[x]<deep[y])swap(x,y);
            for(int i=16;i>=0;i--)
            if(deep[anc[x][i]]>=deep[y])x=anc[x][i];
            if(x==y)return x;
            for(int i=16;i>=0;i--)
            if(anc[x][i]!=anc[y][i])x=anc[x][i],y=anc[y][i];
            return anc[x][0];
        }
        fstc int main()
        {
            G.init();
            register int i,j;
            for(i=1;i<=MX;++i)
            sqr[i]=sqr[i-1]+((sqr[i-1]+1)*(sqr[i-1]+1)==i);
            n=read();
            for(i=1;i<=n;++i)a[i]=read();
            init();
            Q=read();
            while(Q--)
            {
                int opt=read(),s=read(),t=read(),k=read();
                int lca=get_lca(s,t),len=deep[s]+deep[t]-2*deep[lca];
                if(opt==0)
                {
                    if(len%k!=0)modify(t),t=jump(t,len%k);
                    if(deep[lca]%k==deep[s]%k)modify(lca);
                    for(j=1;j<=2;++j)
                    {
                        path_top=0;
                        swap(s,t);
                        int tmp=deep[s]-deep[lca]-1;
                        if(tmp<0)continue ;
                        int pos=jump(s,tmp/k*k);
                        if(k<=K) T[k].get_path(s,pos);
                        else get_path(s,pos,k);
                        for(int i=1;i<=path_top;i++)
                        modify(path[i]);
                    }
                }
                else
                {
                    ll ret=0;
                    if(len%k>0)ret+=a[t],t=jump(t,len%k);
                    if(deep[lca]%k==deep[s]%k)ret+=a[lca];
                    if(k<=K)
                    for(j=1;j<=2;++j)
                    {
                        swap(s,t);
                        int tmp=deep[s]-deep[lca]-1;
                        if(tmp<0)continue ;
                        int pos=jump(s,tmp/k*k);
                        ret+=T[k].ask(s,pos);
                    }
                    else ret+=ask(s,lca,k),swap(s,t),ret+=ask(s,lca,k);
                    write(ret),*ou++='\n';
                }
            }
            fwrite(Out,1,ou-Out,stdout);
            return 0;
    }
    
    • 1

    信息

    ID
    2956
    时间
    10000ms
    内存
    500MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者