bzoj 1537: [POI2005]Aut- The Bus 线段树

bzoj 1537: [POI2005]Aut- The Bus

先把坐标离散化

设f[i][j]表示从(1,1)走到(i,j)的最优解

这样直接dp::: f[i][j] = max{f[i-1][j] + f[i][j-1]} + w[i][j]就可以完美的MLE + TLE了

我们发现f[i][j]中,只有有权的点才有意义,但是我们只有10^5个有用的点,却考虑了10^5 * 10^5个点

所以我们只考虑有权的点,那么可以发现,

f[i][j]的更新一定是由f(1,1)~(i,j)的最大值更新过来的

所以可以用二维树状数组线段树来维护这个东西

我们按照x坐标排序,再按y排序,这样我们发现上一步计算出来的答案才有可能更新下一个计算出来的y值大于这个值的答案

我们可以使用线段树来维护这个东西

:这里使用的是zkw线段树,也就是非递归版线段树

详见《统计的力量》

 #include <queue>
#include <cstdio>
#include <cstring>
#include <climits>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(ll &x){
x=;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=*x+ch-'',ch=getchar(),ch>'!');if(flag) x=-x;
}
inline ll cat_min(const ll &a,const ll &b){return a<b ? a:b;}
inline ll cat_max(const ll &a,const ll &b){return a>b ? a:b;}
inline ll cat_abs(const ll &x){return x < ? -x : x;}
const ll maxn = ;
struct Node{
ll x,y,v;
bool friend operator < (const Node &a,const Node &b){
return a.x == b.x ? a.y < b.y : a.x < b.x;
}
}G[maxn];
ll T[maxn<<],M;
inline void build(ll n){for(M=;M<(n+);M<<=);}
inline void change(ll x,ll val){
if(T[x+=M] >= val) return;
for(T[x]=val,x>>=;x;x>>=)
T[x] = cat_max(T[x<<],T[x<<|]);
}
inline ll query(ll s,ll t){
ll ret = ;
for(s+=M-,t+=M+;s^t^;s>>=,t>>=){
if(~s&) ret = cat_max(ret,T[s^]);
if( t&) ret = cat_max(ret,T[t^]);
}return ret;
}
ll f[maxn];
inline bool cmp(const Node &a,const Node &b){
if(a.y == b.y) return a.x < b.x;
return a.y < b.y;
}
int main(){ ll n,m,k;read(n);read(m);read(k);
for(ll i=;i<=k;++i){
read(G[i].x);read(G[i].y);read(G[i].v);
}
sort(G+,G+k+,cmp);
for(ll i=,n_h = ;i<=k;++i) G[i].y = ++n_h;
build(k);
sort(G+,G+k+);
ll ans = ;
for(ll i=;i<=k;++i){
f[i] = query(,G[i].y) + G[i].v;
change(G[i].y,f[i]);
ans = cat_max(ans,f[i]);
}printf("%lld\n",ans); return ;
}
上一篇:linkin大话数据结构--apache commons工具类


下一篇:hibernate- Hibernate中多对多的annotation的写法(中间表可以有多个字段)