zoukankan      html  css  js  c++  java
  • 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
    ",ans1,ans2);
                out(ans1);
                putchar(' ');
                out(ans2);
                putchar('
    ');
            }
        }
        return 0;
    }
    View Code

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

    没有AC不了的题,只有不努力的ACMER!
  • 相关阅读:
    ImageView的功能和使用
    时钟AnalogClock和DigitalClock
    开发自定义View
    二十二、android中application标签说明
    二十一、Android上常见度量单位【xdpi、hdpi、mdpi、ldpi】解读
    二十、Android -- SDcard文件读取和保存
    十九、android中判断sim卡状态和读取联系人资料的方法
    十八、Android引导界面
    十七、Android学习笔记_Android 使用 搜索框
    十六、Android 滑动效果汇总
  • 原文地址:https://www.cnblogs.com/--560/p/5280469.html
Copyright © 2011-2022 走看看