動態規劃,計數DP,模擬(Persistent Link/cut Tree,HDU 5401)

題目鏈接:https://vjudge.net/problem/HDU-5401


系統相對比較複雜的動態規劃,所以看上去有點像模擬。


參考博客:http://blog.csdn.net/u013007900/article/details/47760825


TEL了好久。

原因是使用了stl的map,被卡了常數。

stl的map的常數大概是自己實現treap的5~10倍

大概是O(1)的15倍以上

如果算上logn的話,在n=100左右的情況下,map是O(1)的100倍左右。

所以如果覺得時間複雜度上界很緊,而且在超時邊緣的話,最好不要用stl。


關於時間複雜度的優化

一個算法的時間複雜度是由其最差的部分決定的,比如O(m(5+(2m)log(2m)+(2m)^2log(2m)))=O(m^3logm),前面有個常數在4左右,或者也可以直接令m=2m。如果使用stl還要乘以一個O(15)的常數。

我們可以考慮將最差部分的一些複雜度轉移到其他部分,使得最差的最小。

比如本題也可以考慮不使用stl,或者改變實現方式,從而去掉常數以及那個logm。

可以使用一些小數組,額外的預處理等來避免使用stl。

具體一點就是使用離散化。

可以對數值排序,去重。

然後利用下標來進行映射的處理。

使用二分來查找。

O(logn)的複雜度在n很大的時候,相對而言是很小的。

但是在n比較小的時候,比如100左右,它的影響力相對而言還是很大的。

主要還是沒算對時間複雜度吧,就是那個stl的常數乘以logm,就大概有O(100)了。


關於實現方面的。

儘量不要寫一個結構體,而要寫成全局的,雖然結構體邏輯會清晰一點,但是代碼量會高很多,思考起來也比較麻煩。

其實各有好處吧,自己看情況抉擇就好了。結構體的話封裝起來不容易錯,也不容易命名衝突。就是在使用的時候會有一些重複的繁瑣的代碼。


代碼

#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int maxm = 65;
const int mod = 1e9+7;

int id[maxm<<1];

struct T
{
    int ans;
    ll num;
    vector<ll>vec;
    ll ju[maxm<<1];
    ll jian[maxm<<1][maxm<<1];
    void init()
    {
        ans=0;
        num=0;
        vec.clear();
    }
}t[maxm];

int m;
int a[maxm],b[maxm],l[maxm];
ll c[maxm],d[maxm];

void read()
{
    t[0].init();
    t[0].num=1;
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d %lld %lld %d",a+i,b+i,c+i,d+i,l+i);
        t[i].init();
    }
}

void getid(int i)
{
    for(int j=0;j<(int)t[i].vec.size();j++)
        if(t[i].vec[j]>=t[a[i]].num)
            id[j]=lower_bound(t[b[i]].vec.begin(),t[b[i]].vec.end(),t[i].vec[j]-t[a[i]].num)-t[b[i]].vec.begin();
        else
            id[j]=lower_bound(t[a[i]].vec.begin(),t[a[i]].vec.end(),t[i].vec[j])-t[a[i]].vec.begin();
}


void solve()
{
    read();
    for(int i=1;i<=m;i++)
        t[i].num=t[a[i]].num+t[b[i]].num;
    for(int i=m;i>=1;i--)
    {
        sort(t[i].vec.begin(),t[i].vec.end());
        t[i].vec.resize(unique(t[i].vec.begin(),t[i].vec.end())-t[i].vec.begin());
        t[a[i]].vec.push_back(c[i]);
        t[b[i]].vec.push_back(d[i]);
        for(int j=0;j<(int)t[i].vec.size();j++)
        {
            ll v = t[i].vec[j];
            if(v>=t[a[i]].num) t[b[i]].vec.push_back(v-t[a[i]].num);
            else t[a[i]].vec.push_back(v);
        }
    }
    for(int i=1;i<=m;i++)
    {
        getid(i);

        t[i].ans=(1ll*t[a[i]].ans+t[b[i]].ans)%mod;
        t[i].ans=(t[i].ans+1ll*t[a[i]].num%mod*(t[b[i]].num%mod)%mod*l[i]%mod)%mod;
        int tp2 = lower_bound(t[b[i]].vec.begin(),t[b[i]].vec.end(),d[i])-t[b[i]].vec.begin();
        t[i].ans=(t[i].ans+1ll*t[a[i]].num%mod*t[b[i]].ju[tp2]%mod)%mod;
        int tp1 = lower_bound(t[a[i]].vec.begin(),t[a[i]].vec.end(),c[i])-t[a[i]].vec.begin();
        t[i].ans=(t[i].ans+1ll*t[b[i]].num%mod*t[a[i]].ju[tp1]%mod)%mod;

        for(int u=0;u<(int)t[i].vec.size();u++)
            if(t[i].vec[u]>=t[a[i]].num)
                t[i].ju[u]=((1ll*t[b[i]].ju[id[u]]+t[a[i]].ju[tp1])%mod
                +1ll*t[a[i]].num%mod*((1ll*l[i]+t[b[i]].jian[tp2][id[u]])%mod)%mod)%mod;
            else
                t[i].ju[u]=((1ll*t[a[i]].ju[id[u]]+t[b[i]].ju[tp2])%mod
                +1ll*t[b[i]].num%mod*((1ll*l[i]+t[a[i]].jian[tp1][id[u]])%mod)%mod)%mod;

        for(int u=0;u<(int)t[i].vec.size();u++)
            for(int v=0;v<(int)t[i].vec.size();v++)
            {
                int d1,d2;
                int f1,f2;
                if(t[i].vec[u]>=t[a[i]].num) d1=t[b[i]].jian[id[u]][tp2],f1=1;
                else d1=t[a[i]].jian[id[u]][tp1],f1=0;

                if(t[i].vec[v]>=t[a[i]].num) d2=t[b[i]].jian[id[v]][tp2],f2=1;
                else d2=t[a[i]].jian[id[v]][tp1],f2=0;

                if(f1!=f2) t[i].jian[u][v]=t[i].jian[v][u]=((1ll*d1+d2)%mod+l[i])%mod;
                else if(f1) t[i].jian[u][v]=t[i].jian[v][u]=t[b[i]].jian[id[u]][id[v]];
                else t[i].jian[u][v]=t[i].jian[v][u]=t[a[i]].jian[id[u]][id[v]];
            }
    }
    for(int i=1;i<=m;i++)
        printf("%d\n",t[i].ans);
}

int main()
{
    while(~scanf("%d",&m)) solve();
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章