zoukankan      html  css  js  c++  java
  • #4613. problem C

    题目描述

    给一棵 $n$ 个点的树,每条边的边权为 $1$ 。

    强制在线。

    有 $m$ 次询问,每次询问给出 $u^{prime}, v^{prime}, w^{prime}$ ,令 $u=left(u^{prime}+ ext {lastans} ight) \% n+1, v= left(v^{prime}+ ext {lastans} ight) \% n+1, w=left(w^{prime}+ ext {lastans} ight) \% n$ , $lastans$ 为上一次询问的答案,初始时 $lastans=0$ 。

    求有多少个点 $x$ 满足, $min (operatorname{dis}(x, u), operatorname{dis}(x, v)) leq w, quad operatorname{dis}(x, y)$ 等于 $x,y$ 在树上的距离

    数据范围

    $1 leq n, m leq 10^{5}, 1 leq u, v, u^{prime}, v^{prime} leq n, 0 leq w, w^{prime}<n$

    题解

    考场不应该想不出的题。

    考虑分别对于 $u,v$ 求出 $dis(u,x) le w$ , $dis(v,x) le w$ 的点数,动态点分即可。

    没想出如何去重,其实还挺简单的,就是 $dis(x,mid) le w-frac{dis(u,v)}{2}$ ,其中 $mid$ 是 $u,v$ 的中点,画个图理解一下吧。这个也可以动态点分。

    为了方便,将边化成点,距离就都是偶数。

    效率: $O(nlogn) sim O(nlog^2n)$ 。

    代码

    #include <bits/stdc++.h>
    using namespace std; const int N=2e5+5,M=N<<1;
    int rt,o,n,m,son[N],sz[N],V[M],nx[M],hd[N],top[N],H,ax[M];
    int a[N],d[N],e[N],f[N],up[N],c,tt,T[M],ans,s[N],ac[N][20];
    bool vis[N];vector<int>g[M];
    void add(int u,int v){
        V[++tt]=v;nx[tt]=hd[u];hd[u]=tt;
    }
    void dfs1(int x,int fa){
        ac[x][0]=f[x]=fa;d[x]=d[fa]+1;sz[x]=1;
        for (int i=1;ac[ac[x][i-1]][i-1];i++)
            ac[x][i]=ac[ac[x][i-1]][i-1];
        for (int i=hd[x];i;i=nx[i])
            if (V[i]!=fa){
                dfs1(V[i],x);sz[x]+=sz[V[i]];
                if (sz[s[x]]<sz[V[i]])
                    s[x]=V[i];
            }
    }
    void dfs2(int x,int tp){
        top[x]=tp;
        if (s[x]) dfs2(s[x],tp);
        for (int i=hd[x];i;i=nx[i])
            if (V[i]!=f[x] && V[i]!=s[x])
                dfs2(V[i],V[i]);
    }
    int lca(int x,int y){
        while(top[x]!=top[y]){
            if (d[top[x]]<d[top[y]])
                swap(x,y);
            x=f[top[x]];
        }
        if (d[x]>d[y]) swap(x,y);return x;
    }
    int dis(int x,int y){
        return d[x]+d[y]-(d[lca(x,y)]<<1);
    }
    void change(int x){
        for (int v,i=x;up[i];i=up[i])
            v=dis(x,up[i]),
            ax[up[i]]=max(ax[up[i]],v),
            ax[i+H]=max(ax[i+H],v);
    }
    void update(int x){
        g[x][0]++;
        for (int v,i=x;up[i];i=up[i])
            v=dis(x,up[i]),g[up[i]][v]++,g[i+H][v]++;
    }
    void getrt(int x,int fa){
        sz[x]=1;son[x]=0;
        for (int i=hd[x];i;i=nx[i])
            if (V[i]!=fa && !vis[V[i]])
                getrt(V[i],x),sz[x]+=sz[V[i]],
                son[x]=max(son[x],sz[V[i]]);
        son[x]=max(son[x],o-sz[x]);
        if (son[x]<son[rt]) rt=x;
    }
    void work(int x,int fa){
        vis[x]=1;up[x]=fa;
        for (int i=hd[x];i;i=nx[i])
            if (!vis[V[i]])
                o=sz[V[i]],rt=0,
                getrt(V[i],x),work(rt,x);
    }
    void go(int x,int y,int w){
        ans+=w*g[x][min(y,ax[x])];
        for (int v,i=x;up[i];i=up[i]){
            v=dis(x,up[i]);
            if (v<=y)
                ans+=w*g[up[i]][min(y-v,ax[up[i]])],
                ans-=w*g[i+H][min(y-v,ax[i+H])];
        }
    }
    int main(){
        son[0]=1e9;scanf("%d%d",&n,&m);H=n;
        for (int x,y,i=1;i<n;i++)
            scanf("%d%d",&x,&y),H++,
            add(x,H),add(H,x),add(y,H),add(H,y);
        dfs1(1,0);dfs2(1,1);o=H;
        getrt(1,0);work(rt,0);tt=0;
        for (int i=1;i<=n;i++) change(i);
        for (int i=1;i<=H+H;i++)
            for (int j=0;j<=ax[i];j++)
                g[i].push_back(0);
        for (int i=1;i<=n;i++) update(i);
        for (int i=1;i<=H+H;i++)
            for (int j=1;j<=ax[i];j++)
                g[i][j]+=g[i][j-1];
        for (int u,v,w,l,x,y;m--;){
            scanf("%d%d%d",&u,&v,&w);
            u=(u+ans)%n+1;v=(v+ans)%n+1;
            w=(w+ans)%n*2;ans=0;go(u,w,1);go(v,w,1);
            l=lca(u,v);y=d[u]+d[v]-(d[l]<<1);
            if (d[u]>d[v]) swap(u,v);x=v;
            for (int i=19;~i;i--)
                if (d[ac[x][i]]>=d[l] && ((d[v]-d[ac[x][i]])<<1)<=y)
                    x=ac[x][i];
            y>>=1;if (w>=y) go(x,w-y,-1);
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    angular7新特性
    ES6基本语法入门
    uni-app 请求封装
    Node.js- Express框架
    webpack知识分享
    【JS】深入理解JS原型和继承
    JavaScript 变量作用域和声明提升
    在元素上写事件和addEventListent()的区别
    webStrom快捷键快速创建React组件
    vue移动端 实现手机左右滑动入场动画
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/11969889.html
Copyright © 2011-2022 走看看