貌似網上大部分題解都是cdq分治+點分治然後再斜率優化dp,我貌似並沒有用這個方法。
這一題跟這題有點像,只不過多了乙個l的限制
如果說直接跑斜率優化dp,儲存整個序列的話,顯然是不行的,如圖所示(圖鳴謝某巨佬)
所以我們需要種一棵線段樹,每個線段樹內儲存乙個存當前區間凸包的單調棧,彈出插入操作跟剛剛說的那題一樣。
查詢的話就查詢下整個區間中所有凸包上的最大值就可以了。
時間複雜度:$o(n\log^2\ n)$。寫起來並不算很困難。
1 #include2#define m 200005
3#define l long long
4#define inf (1ll<<62)
5using
namespace
std;67
struct edgee[m]=; int head[m]=,use=0;8
void add(int x,int y,int z)
9 l d[m]=,p[m]=,q[m]=,f[m]=,n,t,up[m]=;
10double slope(int i,int j)
11 l getans(int x,int y)
1213
int f[m][20]=,dep[m]=;
14int jump(int
x,l dis)
20return max(1
,dep[x]);21}
2223
struct
tb26 tb(int
len)
31int add(int
x)39
if(slope(q[ll],q[ll+1])1],x)) ll++;
40 r=ll;41}
42int res=q[++r]; q[r]=x;
43return
res;44}
45 l getans(int
x)53
if(slope(q[ll],q[ll+1])
54return q[ll+1
];55
return
q[ll];56}
57};
5859
struct nodea[m*3
];60
void build(int x,int l,int
r)66
void updata(int x,int k,int id,int lastl,int lastr,int
lastt)
73void reset(int x,int k,int lastl,int lastr,int
lastt)
80 l query(int x,int l,int r,int
k)88
89void dfs(int x,int
fa,l dis),lastr[20]=,lastt[20]=;
95 updata(1
,dep[x],x,lastl,lastr,lastt);
96for(int i=head[x];i;i=e[i].next) dfs(e[i].u,x,dis+e[i].v);
97 reset(1
,dep[x],lastl,lastr,lastt);98}
99int
main()
105 build(1,1
,n);
106int hh[20]; updata(1,1,1
,hh,hh,hh);
107 dep[1]=1; d[0]=-inf;
108for(int i=head[1];i;i=e[i].next) dfs(e[i].u,1
,e[i].v);
109for(int i=2;i<=n;i++) printf("
%lld\n
",f[i]);
110 }
NOI2014 購票 樹上斜率優化
首先易得方程,且經過變換有 begin f i min limits f j p idist j f i dist ip i q i end 在一條直線上時,斜率優化可以用普通 cdq 分治實現 會不會過於麻煩?那麼對於在樹上斜率優化時,考慮點分治 這時就在點分治中運用 cdq 分治的思想,即使用在...
NOI2014 購票(樹形dp 樹剖 斜率優化)
考慮樹形 dp,設 dpi dp i dpi 為 ii i 節點到 sz 市的最小費用,dis idis i disi 為 sz 市到 i ii 節點的距離。顯然初始化 dp1 0 dp 1 0 dp1 0 然後 dis idis i disi 可以提前預處理出來。然後有 dpu min dpv d...
NOI2014 購票(樹形dp 樹剖 斜率優化)
考慮樹形 dp,設 dpi dp i dpi 為 ii i 節點到 sz 市的最小費用,dis idis i disi 為 sz 市到 i ii 節點的距離。顯然初始化 dp1 0 dp 1 0 dp1 0 然後 dis idis i disi 可以提前預處理出來。然後有 dpu min dpv d...