CF372C Watching Fireworks is Fun 题解
Problem:CF372C~ Watching~ Fireworks~Is ~Fun
Description
一个城镇有
节日中有
你每个单位时间可以移动不超过
Solution
先思考用什么算法。
如果是贪心,实际上是不好贪心的,因为它有多个参数。是蒟蒻的我也不会贪心
贪心不行,瞧上去又像是道乱搞题,那肯定是
思考朴素
设
推导方程
可见
朴素
但是看时间复杂度最大
同时的数组
先解决空间问题
优化1:
容易想到滚动数组第一维
优化2:
同时求
再想如何解决时间问题
优化3:
我们枚举
Code
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MaxN=152000;
ll n,m,d,sum;
ll a[MaxN],b[MaxN],t[MaxN],f[2][152000],q[MaxN];
template <class G> inline void read(G&x){
bool f;char ch=getchar();
for(f=false;!isdigit(ch);ch=getchar())if(ch=='-')f=true;
for(x=0;isdigit(ch);x=(x<<1)+(x<<3)+(ch^48),ch=getchar());
x*=f==1?-1:1;
}
inline int abs(int x){
if(x<0) return -x;
return x;
}
signed main(){
read(n),read(m),read(d);
memset(f,0x3f3f3f,sizeof(f));
for(register int i=1;i<=m;i++) read(a[i]),read(b[i]),read(t[i]),sum+=b[i];
for(register int i=1;i<=n;i++) f[1][i]=abs(a[1]-i);
for(register int i=2;i<=m;i++){
int now=i&1,last=i&1^1,ti=t[i]-t[i-1];
memset(f[now],0x3f3f3f,sizeof(f[now]));
int head=1,tail=0;
for(register int j=1;j<=n;j++){
while (head<=tail&&q[head]<j-ti*d) ++head;
while (head<=tail&&f[last][q[tail]]>f[last][j]) --tail;
q[++tail]=j;
f[now][j]=min(f[now][j],f[last][q[head]]+abs(a[i]-j));
}
head=1,tail=0;
for(register int j=n;j>=1;j--){
while (head<=tail&&q[head]>j+ti*d) ++head;
while (head<=tail&&f[last][q[tail]]>f[last][j]) --tail;
q[++tail]=j;
f[now][j]=min(f[now][j],f[last][q[head]]+abs(a[i]-j));
}
}
ll ans=INT_MAX/2;
for(register int i=1;i<=n;i++) ans=min(f[m&1][i],ans);
cout<<sum-ans;
return 0;
}
Postscript
这只是一道很
也感谢其他奆佬写的题解对我的帮助
更多的单调队列优化
1. [POI2014]PTA-Little Bird(板子).
2. [NOI2011]Noi嘉年华
希望大家对单调队列优化的
C_{s_p}~_20^{1^9}~P_{l^us}~P^{l_{u_s}}
希望各位考完联赛能和最爱的人好好看一场烟花