原题O(nm),但我们可以做到O(mlogm)
RedLycoris · · 题解
CF372C Watching Fireworks is Fun
我们可以换种思考方式来解决这个问题。
显然
令
假设我们已经考虑了前
令
然后每燃放一场烟花,我们就相当于对
综上,可以发现,这个
考虑继续优化。
发现这个
这启发我们可以维护两个优先队列一样的东西,一个维护左半段斜率小于
我们考虑在这种维护方式下,等待时间和加入烟花秀各有什么影响。
由于这个
当然,我们没有必要真的去减一遍,我们只需要维护两个全局减去/加上的
再考虑这个加入烟花的操作。
令左半段最右边的转折点横坐标为
-
l<a_i<r
此时就相当于
-
a_i \le l
此时
所以我们加入两边
-
a_i \ge r
和上一种情况同理。
综上,时间复杂度
Code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,d,ans,tag,pre;
priority_queue<int>L;
priority_queue<int,vector<int>,greater<int> >R;
signed main(){
ios_base::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>m>>d;
for(int i=1;i<=m;++i){
int a,b,t;cin>>a>>b>>t;
ans+=b;
if(i==1)L.push(a),R.push(a),pre=t;
else{
tag+=d*(t-pre);
int l=L.top()-tag,r=R.top()+tag;
if(a<l)L.pop(),L.push(a+tag),L.push(a+tag),R.push(l-tag),ans-=l-a;
else if(a>r)R.pop(),R.push(a-tag),R.push(a-tag),L.push(r+tag),ans-=a-r;
else L.push(a+tag),R.push(a-tag);
}
pre=t;
}
cout<<ans<<'\n';
}