#include
#include
#include
#include
using namespace std;
#define ll long long
deque < pair < int, ll > > q;
int n, m, k;
ll ans, sum;
ll a[5005];
ll dp[5005][5005];
/*
dp[i][j]=max(dp[p-1][j-1]+a[p]) {p=[i-k+1,i]}
前i个数中选j个的最大值
用单调队列优化dp[p-1][j-1]+a[p](因为与i无关)
*/
int main() {
scanf( "%d %d %d", &n, &k, &m );
for( int i = 1;i <= n;i ++ )
scanf( "%lld", &a[i] );
memset( dp, -1, sizeof( dp ) );
for( int i = 0;i < k;i ++ ) dp[i][0] = 0;//前k-1个不选也是可以成立的
//为什么不是0~n呢?
//因为如果n>k,题目要求每连续的k个元素都至少有一个要选
//所以显然dp[n][0]是不成立的
for( int j = 1;j <= m;j ++ ) {
while( ! q.empty() ) q.pop_back();
for( int i = j;i <= n;i ++ ) {
while( ! q.empty() && q.front().first < i - k + 1 ) q.pop_front();
if( ~ dp[i - 1][j - 1] ) {//这个相当于i作上一层状态,去转移后面的
while( ! q.empty() && q.back().second <= dp[i - 1][j - 1] + a[i] )
q.pop_back();
q.push_back( make_pair( i, dp[i - 1][j - 1] + a[i] ) );
}
if( ! q.empty() ) dp[i][j] = q.front().second;//这个相当于i作当前层状态,被上层状态转移
}
}
printf( "%lld", dp[n][m] );
return 0;
}
只会往后砍,绝对不吃回头草
d p [ i ] dp[i] dp[i]表示砍掉第 i i i棵树的最小花费
枚举前面砍掉的数的最大编号
d p [ i ] = d p [ j ] + a [ i ] ∗ b [ j ] dp[i]=dp[j]+a[i]*b[j] dp[i]=dp[j]+a[i]∗b[j]
d p [ i ] = d p [ k ] + a [ i ] ∗ b [ k ] dp[i]=dp[k]+a[i]*b[k] dp[i]=dp[k]+a[i]∗b[k]
m i n ( d p [ j ] + a [ i ] ∗ b [ j ] , d p [ k ] + a [ i ] ∗ b [ k ] ) min(dp[j]+a[i]*b[j],dp[k]+a[i]*b[k]) min(dp[j]+a[i]∗b[j],dp[k]+a[i]∗b[k])
如果 k k k优于 j j j则有
d p [ j ] + a [ i ] ∗ b [ j ] > = d p [ k ] + a [ i ] ∗ b [ k ] dp[j]+a[i]*b[j]>=dp[k]+a[i]*b[k] dp[j]+a[i]∗b[j]>=dp[k]+a[i]∗b[k]
d p [ j ] − d p [ k ] > = a [ i ] ∗ ( b [ k ] − b [ j ] ) j < k , b [ j ] > b [ k ] dp[j]-dp[k]>=a[i]*(b[k]-b[j]) {j
( d p [ j ] − d p [ k ] ) / ( b [ k ] − b [ j ] ) < = a [ i ] (dp[j]-dp[k])/(b[k]-b[j])<=a[i] (dp[j]−dp[k])/(b[k]−b[j])<=a[i]
#include
#include
using namespace std;
#define ll long long
int n, head = 1, tail;
ll high[100005], cost[100005], deq[100005], dp[100005];
double calc( int j, int k ) {
return ( dp[j] - dp[k] ) * 1.0 / ( cost[k] - cost[j] );
}
int main() {
scanf( "%d", &n );
for( int i = 1;i <= n;i ++ )
scanf( "%lld", &high[i] );
for( int i = 1;i <= n;i ++ )
scanf( "%lld", &cost[i] );
for( int i = 1;i <= n;i ++ ) {
while( head < tail && calc( deq[head], deq[head + 1] ) <= high[i] ) head ++;
if( head <= tail ) dp[i] = dp[deq[head]] + high[i] * cost[deq[head]];
while( head < tail && calc( deq[tail - 1], deq[tail] ) >= calc( deq[tail], i ) ) tail --;
deq[++ tail] = i;
}
printf( "%lld", dp[n] );
return 0;
}
希望谢特姐姐崽也可以和自己最爱的人——谢特姐姐一起看一场美丽绚烂的烟花盛宴
#include
#include
#include
using namespace std;
#define ll long long
int n, m, d, head, tail;
ll sum, ans;
int deq[150005];
ll a[305], b[305], t[305];
ll f[2][150005];
ll Fabs( ll x ) {
return ( x > 0 ) ? x : -x;
}
int main() {
scanf( "%d %d %d", &n, &m, &d );
for( int i = 1;i <= m;i ++ ) {
scanf( "%lld %lld %lld", &a[i], &b[i], &t[i] );
sum += b[i];
}
for( int i = 1;i <= n;i ++ )
f[1][i] = Fabs( a[1] - i );
for( int i = 2;i <= m;i ++ ) {
int now = i & 1, last = i & 1 ^ 1;
memset( f[now], 0x3f, sizeof( f[now] ) );
ll T = t[i] - t[i - 1];
head = 1, tail = 0;
for( int j = 1;j <= n;j ++ ) {
while( head <= tail && deq[head] < j - T * d ) head ++;
while( head <= tail && f[last][deq[tail]] >= f[last][j] ) tail --;
deq[++ tail] = j;
f[now][j] = min( f[now][j], f[last][deq[head]] + Fabs( a[i] - j ) );
}
head = 1, tail = 0;
for( int j = n;j;j -- ) {
while( head <= tail && deq[head] > j + T * d ) head ++;
while( head <= tail && f[last][deq[tail]] >= f[last][j] ) tail --;
deq[++ tail] = j;
f[now][j] = min( f[now][j], f[last][deq[head]] + Fabs( a[i] - j ) );
}
}
ll ans = 0x7f7f7f7f;
for( int i = 1;i <= n;i ++ )
ans = min( ans, f[m & 1][i] );
printf( "%lld", sum - ans );
return 0;
}
#include
#include
#include
using namespace std;
#define ll long long
deque < int > q;
int n;
ll ans;
ll a[100005], dp[100005];
int main() {
scanf( "%d", &n );
for( int i = 1;i < n;i ++ )
scanf( "%lld", &a[i] );
dp[n - 1] = ans = 1;
q.push_back( n - 1 );
for( int i = n - 2;i;i -- ) {
int k = * ( upper_bound( q.rbegin(), q.rend(), a[i] ) - 1 );
dp[i] = dp[k] + ( n - a[i] ) + ( k - i );
ans += dp[i];
while( ! q.empty() && a[q.back()] <= a[i] ) q.pop_back();
q.push_back( i );
}
printf( "%lld", ans );
return 0;
}
#include
#include
#include
using namespace std;
#define MAXM 20005
int n, m, k, g;
int tree[MAXM << 2], lazy[MAXM << 2];
int s[55][MAXM], a[55][MAXM];
int f[55][MAXM];
void build( int t, int l, int r, int i ) {
if( l == r ) {
tree[t] = f[i][l] + s[i + 1][l + k - 1] - s[i + 1][l - 1];
return;
}
int mid = ( l + r ) >> 1;
build( t << 1, l, mid, i ), build( t << 1 | 1, mid + 1, r, i );
tree[t] = max( tree[t << 1], tree[t << 1 | 1] );
}
void push_down( int t ) {
if( lazy[t] ) {
tree[t << 1] += lazy[t], tree[t << 1 | 1] += lazy[t];
lazy[t << 1] += lazy[t], lazy[t << 1 | 1] += lazy[t];
lazy[t] = 0;
}
}
void modify( int t, int l, int r, int L, int R, int val ) {
if( L <= l && r <= R ) {
lazy[t] += val, tree[t] += val;
return;
}
push_down( t );
int mid = ( l + r ) >> 1;
if( L <= mid ) modify( t << 1, l, mid, L, R, val );
if( mid < R ) modify( t << 1 | 1, mid + 1, r, L, R, val );
tree[t] = max( tree[t << 1], tree[t << 1 | 1] );
}
void add( int i, int pos ) {//重复贡献
if( pos ) modify( 1, 1, g, max( 1, pos - k + 1 ), min( g, pos ), -a[i][pos] );
}
void del( int i, int pos ) {
if( pos ) modify( 1, 1, g, max( 1, pos - k + 1 ), min( pos, g ), a[i][pos] );
}
int main() {
scanf( "%d %d %d", &n, &m, &k );
for( int i = 1;i <= n;i ++ )
for( int j = 1;j <= m;j ++ )
scanf( "%d", &a[i][j] ), s[i][j] = s[i][j - 1] + a[i][j];
g = m - k + 1;
for( int i = 1;i <= n;i ++ ) {
if( i > 1 )
for( int j = 1;j < k;j ++ )
add( i, j );
for( int j = 1;j + k - 1 <= m;j ++ ) {
int l = j, r = j + k - 1;
if( i == 1 ) f[i][j] = s[1][r] - s[1][l - 1];
else del( i, l - 1 ), add( i, r ), f[i][j] = tree[1] + s[i][r] - s[i][l - 1];
}
memset( tree, 0, sizeof( tree ) );
memset( lazy, 0, sizeof( lazy ) );
if( i < n ) build( 1, 1, g, i );
}
int ans = 0;
for( int i = 1;i <= m;i ++ )
ans = max( ans, f[n][i] );
printf( "%d", ans );
return 0;
}
#include
#include
using namespace std;
#define ll long long
struct node {
ll f, maxx, ans;
node(){}
node( ll x, ll y, ll z ) {
f = x, maxx = y, ans = z;
}
}q[300005];
int n, top;
ll a, ans;
ll d[300005], F[300005], sum[300005];
ll calc( ll x, ll y ) {
return ( x - y ) * ( x - y );
}
int main() {
scanf( "%d %lld", &n, &a );
for( int i = 1;i <= n;i ++ ) {
ll c;
scanf( "%lld %lld", &d[i], &c );
sum[i] = sum[i - 1] + c;
F[i] = i * a - sum[i];
}
ans = max( 0ll, a - sum[n] + sum[n - 1] );
q[++ top] = node( F[n], 0, F[n] );
q[0].ans = -1e17;
for( int i = n - 1;i;i -- ) {
ll temp = -1e17;
while( top && q[top].maxx <= d[i + 1] - d[i] ) temp = max( temp, q[top].f ), top --;
if( temp != -1e17 )
q[++ top] = node( temp, d[i + 1] - d[i], max( q[top - 1].ans, temp - calc( d[i + 1], d[i] ) ) );
q[++ top] = node( F[i], 0, max( F[i], q[top - 1].ans ) );
ans = max( ans, q[top].ans - a * i + sum[i - 1] + a );
}
printf( "%lld", ans );
return 0;
}
#include
#include
using namespace std;
#define ll long long
#define MAXN 1000005
struct node {
ll x, y, a;
}v[MAXN];
int n;
int deq[MAXN];
ll f[MAXN];
bool cmp( node s, node t ) {
return s.y > t.y;
}
/*
f[i]: 做到排序后的第i个矩形了,选择这个矩形,面积并减去权值和的最大值为f[i]
f[i]=max(f[j]+x[i]*y[i]-x[j]*y[i]-a)
j x[j]<=x[k]
f[j] -x[j]*y[i]<=f[k] -x[k]*y[i]
f[j]-f[k]<=(x[j]-x[k])*y[i]
(f[j]-f[k])/(x[j]-x[k])>=y[i]
*/
double slope( int j, int k ) {
return ( f[j] - f[k] ) * 1.0 / ( v[j].x - v[k].x );
}
int main() {
scanf( "%d", &n );
for( int i = 1;i <= n;i ++ )
scanf( "%lld %lld %lld", &v[i].x, &v[i].y, &v[i].a );
sort( v + 1, v + n + 1, cmp );
int head = 1, tail = 0;
ll ans = 0;
for( int i = 1;i <= n;i ++ ) {
while( head < tail && slope( deq[head], deq[head + 1] ) >= v[i].y )
head ++;
f[i] = v[i].x * v[i].y - v[i].a;
f[i] = max( f[i], f[deq[head]] + v[i].x * v[i].y - v[deq[head]].x * v[i].y - v[i].a );
ans = max( ans, f[i] );
while( head < tail && slope( deq[tail - 1], deq[tail] ) <= slope( deq[tail], i ) )
tail --;
deq[++ tail] = i;
}
printf( "%lld", ans );
return 0;
}
#include
#include
#include
using namespace std;
#define ll long long
const int inf = 1e9;
int n, k, head, tail;
int deq[200010];
ll l, r;
ll dp[2][200010];
int main() {
scanf( "%d %d", &n, &k );
for( int i = 1;i <= n;i ++ )
dp[0][i] = inf;
int now = 0;
while( k -- ) {
scanf( "%lld %lld", &l, &r );
now ^= 1, head = 1, tail = 0;
memcpy( dp[now], dp[now ^ 1], sizeof( dp[now ^ 1] ) );
for( int j = 0;j <= min( r, 1ll * n );j ++ ) {
while( head <= tail && deq[head] < j - ( r - l ) )
head ++;
while( head <= tail && dp[now ^ 1][deq[tail]] >= dp[now ^ 1][j] )
tail --;
deq[++ tail] = j;
dp[now][j] = min( dp[now][j], dp[now ^ 1][deq[head]] + 2 );
}
head = 1, tail = 0;
for( int j = r;~ j;j -- ) {
while( head <= tail && deq[head] < l - j )
head ++;
while( head <= tail && dp[now ^ 1][deq[tail]] >= dp[now ^ 1][r - j] )
tail --;
deq[++ tail] = r - j;
dp[now][j] = min( dp[now][j], dp[now ^ 1][deq[head]] + 1 );
}
}
if( dp[now][n] ^ inf ) return ! printf( "Full\n%lld", dp[now][n] );
else return ! printf( "Hungry" );
return 0;
}
#include
#include
#include
using namespace std;
#define ll long long
int n, m, p, head, tail;
int deq[100005];
ll d[100005], T[100005], Sum[100005];
ll f[100005][105];
double slope( int j, int k, int i ) {
return ( f[j][i] - f[k][i] + Sum[j] - Sum[k] ) * 1.0 / ( j - k );
}
int main() {
scanf( "%d %d %d", &n, &m, &p );
for( int i = 2;i <= n;i ++ )
scanf( "%lld", &d[i] ), d[i] += d[i - 1];
for( int i = 1;i <= m;i ++ ) {
ll h, t;
scanf( "%lld %lld", &h, &t );
T[i] = t - d[h];
}
if( m <= p ) return ! printf( "0" );
sort( T + 1, T + m + 1 );
for( int i = 1;i <= m;i ++ )
Sum[i] = Sum[i - 1] + T[i];
memset( f, 0x7f, sizeof( f ) );
f[0][0] = 0;
for( int i = 1;i <= p;i ++ ) {
head = tail = 1, deq[0] = 0;
for( int j = 1;j <= m;j ++ ) {
while( head < tail && slope( deq[head], deq[head + 1], i - 1 ) <= T[j] )
++ head;
f[j][i] = f[deq[head]][i - 1] + T[j] * ( j - deq[head] ) - Sum[j] + Sum[deq[head]];
while( head < tail && slope( deq[tail - 1], deq[tail], i - 1 ) >= slope( deq[tail], j, i - 1 ) )
-- tail;
deq[++ tail] = j;
}
}
printf( "%lld", f[m][p] );
return 0;
}