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\n",ans[0],ans[1]);
        else puts("No solution");
    }
}

 

posted @ 2017-03-03 09:54  Candy?  阅读(154)  评论(0编辑  收藏  举报