题目链接: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;
}