題目鏈接: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;
}