zoukankan      html  css  js  c++  java
  • HDU D Tree [点分治]

    传送门

    题意:找路径积$mod 1e6+3 = k$的字典序最小点对


    作为一个点分治蒟蒻,写这道题花了两节课....

    显然只要开一个桶$c[i]$记录当前路径积为$i$的最小点

    然后处理一个子树时一个个子树遍历更新答案再更新$c$就行了

    最后再把$c$复原

    可以用一个栈记下更改过的$c$,但貌似比在遍历一遍树更慢?

    然后注意更新和复原$c[w[u]]$

    好了回教室上数学课啦

    #pragma comment(linker,"/STACK:102400000,102400000")
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const int N=1e5+5,M=1e6+5,P=1e6+3,INF=1e9;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int n;ll k,w[N];
    struct edge{
        int v,ne;
    }e[N<<1];
    int h[N],cnt;
    inline void ins(int u,int v){
        cnt++;
        e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
        cnt++;
        e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
    }
    int inv[M];
    void iniInv(){
        inv[1]=1;
        for(int i=2;i<P;i++)
            inv[i]=(ll)(P-P/i)*inv[P%i]%P;
    }
    
    int size[N],f[N],vis[N],root,allSize;
    void dfsRt(int u,int fa){
        size[u]=1;f[u]=0;
        for(int i=h[u];i;i=e[i].ne){
            int v=e[i].v;
            if(vis[v]||v==fa) continue;
            dfsRt(v,u);
            size[u]+=size[v];
            f[u]=max(f[u],size[v]);
        }
        f[u]=max(f[u],allSize-size[u]);
        if(f[u]<f[root]) root=u;
    }
    int c[M],ans[2];
    int st[N],top;
    void dfsDee(int u,int fa,int now){
        if(!c[now]) c[now]=u;//,st[++top]=now;
        else c[now]=min(c[now],u);
        for(int i=h[u];i;i=e[i].ne){
            int v=e[i].v;
            if(!vis[v]&&v!=fa) dfsDee(v,u,now*w[v]%P);
        }
    }
    void dfsAns(int u,int fa,int now){
        int x=c[k*inv[now]%P],y=u;
        if(x){
            if(x>y) swap(x,y);
            if(x<ans[0]||(x==ans[0]&&y<ans[1])) ans[0]=x,ans[1]=y;
        }
        for(int i=h[u];i;i=e[i].ne){
            int v=e[i].v;
            if(!vis[v]&&v!=fa) dfsAns(v,u,now*w[v]%P);
        }
    }
    void dfsRec(int u,int fa,int now){
        c[now]=0;
        for(int i=h[u];i;i=e[i].ne){
            int v=e[i].v;
            if(!vis[v]&&v!=fa) dfsRec(v,u,now*w[v]%P);
        }
    }
    void dfsSol(int u){
        vis[u]=1;
        c[w[u]]=u;
        for(int i=h[u];i;i=e[i].ne){
            int v=e[i].v;
            if(!vis[v]){
                dfsAns(v,u,w[v]);
                dfsDee(v,u,w[u]*w[v]%P);
            }
        }
        //while(top) c[st[top]]=0,top--;
        for(int i=h[u];i;i=e[i].ne) if(!vis[e[i].v]) dfsRec(e[i].v,u,w[u]*w[e[i].v]%P);
        c[w[u]]=0;
        for(int i=h[u];i;i=e[i].ne){
            int v=e[i].v;
            if(!vis[v]){
                root=0;allSize=size[v];
                dfsRt(v,0);
                dfsSol(root);
            }
        }
    }
    int main(){
        freopen("in","r",stdin);
        iniInv();
        while(scanf("%d%lld",&n,&k)!=EOF){
            memset(vis,0,sizeof(vis));
            cnt=0;memset(h,0,sizeof(h));
            memset(c,0,sizeof(c));
            for(int i=1;i<=n;i++) w[i]=read();
            for(int i=1;i<=n-1;i++) ins(read(),read());
            ans[0]=ans[1]=INF;
            f[0]=INF;
            root=0;allSize=n;
            dfsRt(1,0);
            dfsSol(root);
            if(ans[0]!=INF) printf("%d %d
    ",ans[0],ans[1]);
            else puts("No solution");
        }
    }
  • 相关阅读:
    Flask把变量注册到模板中
    $.each与$(data).each区别
    【Python备忘】python判断文件和文件夹是否存在
    ISP图像质量自动化测试方法
    使用微软的(how-old.net)构建智能门店管理系统
    在virtualenv中安装libxml2和libxslt
    Python 装饰器学习以及实际使用场景实践
    tensorflow零起点快速入门(4) --入门常用API
    tensorflow零起点快速入门(3)
    树莓派和STM32通过USB和串口通信记录
  • 原文地址:https://www.cnblogs.com/candy99/p/6494634.html
Copyright © 2011-2022 走看看