T1:dp。
设f[i][j]表示从i到j的一段在一个月内完成的总共的最少月数(i<=j),那么我们需要枚举一个k,表示k到i-1的一段也在一个月内完成。于是就可以从f[k][i-1]转移到f[i][j]。
那么有以下两种情况:
1、若sum(b[l])+sum(a[r])<=m(k<=l<i)(i<=r<=j),那么f[i][j]=min(f[i][j],f[k][i-1]+1),这种情况表示的是两段可以在一个月内解决。
2、若sum(b[l])+sum(a[r])>m(k<=l<i)(i<=r<=j),那么f[i][j]=min(f[i][j],f[k][i-1]+2),这种情况表示的是两段不能在同一个月内完成,需要多加一个月来还债。
当然,要执行转移的前提条件都是sum(a[k~i-1])<=m&sum(b[k~i-1]<=m)&sum(a[i~j])<=m&sum(b[i~j])<=m。
T2:把RMQ用在树上。
设f[i][j]表示节点i向根走2^j的答案
p[i][j]表示节点i向根走2^j的最大值
g[i][j]表示节点i向根走2^j的最小值
fa[i][j]表示节点i的2^j级祖先(不包括i)
那么我们先dfs一遍求出fa,fa[i][j]=fa[fa[i][j-1]][j-1]。
然后dfs一遍求出p与g,p[i][j]=max(p[fa[i][j-1]][j-1],p[i][j-1]),g只需把max改成min就行了。
接着dfs一遍求出f,f[i][j]=max(f[fa[i][j-1]][j-1],f[i][j-1],p[fa[i][j-1]][j-1]-g[i][j-1])。
最后求ans。设输入的为x,y,那么我们用递归来做。
我们每次找出一个最大的k使得2^k<=y,然后用f[x][k]去更新ans,接着把y减去2^k,x改成fa[x][k],直到y=0为止。
有一个地方要注意,我们每次都要更新一个last,last表示为当前的最小值,last=min(last,g[x][y]),然后我们每次还要用p[x][y]-last来更新ans。
T3:我们先要发现一个性质,就是或运算的值不会减少。所以我们可以用线段树来维护或的值,然后枚举左端点,二分右端点,更新答案。