动态规划,计数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;
}


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