hdu4812 D Tree 点分治

这里要求输出字典序最小的两个点,就不能像之前那样容斥了,只能直接搞了。

直接搞的话,需要避开n^2,由于这里是等式,显然应该考虑hash映射。从前往后依次枚举计算每棵子树,对于每个子树结点,快速从前面已经计算过的子树中找到答案更新就可以了。

很简单的东西,只是难以用文字解释得清楚。大概一般点分治不用容斥直接搞大多是这样干吧。

#pragma comment(linker,"/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<map>
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define MS0(a) memset(a,0,sizeof(a))

using namespace std;

typedef long long ll;
const int maxn=1000100;
const int INF=1e9+10;

template<class T>
inline void scan(T &ret)
{
    char c=getchar();
    while(!isdigit(c)) c=getchar();
    ret=c-'0';
    while(isdigit(c=getchar())) ret=ret*10+c-'0';
}

inline void out(int a)
{
    if(a>9) out(a/10);
    putchar(a%10+'0');
}

const ll MOD=1e6+3;
int N,K;
int val[maxn];
//vector<int> G[maxn];
int u,v;
int ans1,ans2;
int id[maxn];
int d[maxn],dn;
ll s[maxn];
bool vis[maxn];
int rt,balance;
int Inv[maxn];
int e[maxn],tot;
int first[maxn],Next[maxn];

void Init()
{
    tot=0;
    memset(first,-1,sizeof(first));
}

void addedge(int u,int v)
{
    e[++tot]=v;
    Next[tot]=first[u];
    first[u]=tot;
}

ll mul(ll a,ll b,ll MOD)
{
    return (a*b)%MOD;
}

ll qpow(ll n,ll k,ll p)
{
    ll res=1;
    while(k){
        if(k&1) res=(res*n)%p;
        n=(n*n)%p;
        k>>=1;
    }
    return res;
}

void dfs_d(int u,int f,ll dep)
{
    d[++dn]=u;
    s[u]=dep;
    //for(int i=0;i<G[u].size();i++){
    for(int p=first[u];~p;p=Next[p]){
        int v=e[p];
        if(v==f||vis[v]) continue;
        dfs_d(v,u,mul(dep,val[v],MOD));
    }
}

ll inv(ll a,ll p)
{
    return qpow(a,p-2,p);
}

void update(int x,int y)
{
    if(x>y) swap(x,y);
    if(x<ans1) ans1=x,ans2=y;
    else if(x==ans1){
        if(y<ans2) ans1=x,ans2=y;
    }
}

int get_rt(int u,int f,int sz)
{
    int cnt=1,balance1=0;
    for(int p=first[u];~p;p=Next[p]){
        int v=e[p];
        if(v==f||vis[v]) continue;
        int tmp=get_rt(v,u,sz);
        cnt+=tmp;
        balance1=max(balance1,tmp);
    }
    balance1=max(balance1,sz-cnt);
    if(balance1<balance){
        balance=balance1;
        rt=u;
    }
    return cnt;
}

void cls_id(int u,int f)
{
    id[s[u]]=0;
    //for(int i=0;i<G[u].size();i++){
    for(int p=first[u];~p;p=Next[p]){
        int v=e[p];
        if(v==f||vis[v]) continue;
        cls_id(v,u);
    }
}

void solve(int u)
{
    rt=u,balance=INF;
    int sz=get_rt(u,0,N);
    rt=u,balance=INF;
    get_rt(u,0,sz);
    u=rt;
    //cout<<"u="<<u<<endl;
    vis[u]=1;
    id[val[u]]=u;
    s[u]=val[u];
    //for(int i=0;i<G[u].size();i++){
    for(int p=first[u];~p;p=Next[p]){
        int v=e[p];
        if(vis[v]) continue;
        dn=0;
        dfs_d(v,u,mul(val[u],val[v],MOD));
        //cout<<" v="<<v<<" dn="<<dn<<endl;
        //REP(j,1,dn) cout<<d[j]<<"_";cout<<endl;
        int idx,x,idy;
        REP(j,1,dn){
            idx=d[j],x=s[idx];
            idy=id[mul(mul(K,val[u],MOD),Inv[x],MOD)];
            if(idy) update(idx,idy);
        }
        REP(j,1,dn){
            idx=d[j],x=s[idx];
            if(id[x]) id[x]=min(id[x],idx);
            else id[x]=idx;
        }
    }
    cls_id(u,0);
    //for(int i=0;i<G[u].size();i++){
    for(int p=first[u];~p;p=Next[p]){
        int v=e[p];
        if(vis[v]) continue;
        solve(v);
    }
}

void play()
{
    freopen("in.txt","w",stdout);
    int n=10000,k=120;
    cout<<n<<" "<<k<<endl;
    REP(i,1,n) cout<<i<<" ";cout<<endl;
    REP(i,1,n-1){
        cout<<i<<" "<<i+1<<endl;
    }
}

void Init_inv()
{
    REP(i,0,MOD-1) Inv[i]=inv(i,MOD);
}

int main()
{
    //play();return 0;
    freopen("in.txt","r",stdin);
    Init_inv();
    while(~scanf("%d%d",&N,&K)){
        Init();
        REP(i,1,N) scan(val[i]),val[i]%=MOD;
        REP(i,1,N-1){
            //scanf("%d%d",&u,&v);
            scan(u);scan(v);
            addedge(u,v);
            addedge(v,u);
        }
        ans1=ans2=INF;
        MS0(vis);MS0(id);
        solve(1);
        if(ans1==INF) puts("No solution");
        else{ //printf("%d %d\n",ans1,ans2);
            out(ans1);
            putchar(' ');
            out(ans2);
            putchar('\n');
        }
    }
    return 0;
}
View Code

TLE了几次,以为是算法问题,看标程都加了输入输出挂,我也加了试交一下,过了。。。是在下输了。。。

 

posted @ 2016-03-15 17:46  __560  阅读(434)  评论(0编辑  收藏  举报