专栏文章
题解:P12247 跳舞机
P12247题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mipk4608
- 此快照首次捕获于
- 2025/12/03 13:18 3 个月前
- 此快照最后确认于
- 2025/12/03 13:18 3 个月前
跳舞机
题目大意
小 O 有一台跳舞机, 个人在 分钟内游玩,每个人在 到 的时间内游玩,跳舞时间固定为 。
解析
显然在同一时间段 到 内每个人只有在场与不在场两种情况,我们可以贪心的选择能玩中兴奋值 最大的人跳舞(下文用 表示)。
对于不同时间段的选择可以想到 DP ,我们可以设 是在第 分钟内取得的最大兴奋值,可以在第 分钟内可以选择不跳舞,也可以在第 分钟到第 分钟内跳舞, DP 方程就得出了:
不难发现一个人只有在 到 分钟才有可能开始跳舞,于是可以求出从 分钟开始的最大兴奋值 ,但一个一个找肯会 TLE ,我们可以用线段树来完成区间修改,单点查询。最终时间复杂度为 。
AC 记录。
代码
CPP#include <bits/stdc++.h>
using namespace std;
const int N=5e5+10;
struct player{int l,r,w;};
struct linetree{int l,r,val;};
int n,m,k;
long long dp[N];//DP数组
player f[N];
linetree tr[N<<2];//线段树
void pushdown(int u){//把父节点的值传给子代
tr[u<<1].val=max(tr[u<<1].val,tr[u].val);
tr[u<<1|1].val=max(tr[u<<1|1].val,tr[u].val);
}
void build(int u,int l,int r){//建树
tr[u].l=l,tr[u].r=r;
if(l!=r){
int mid=l+r>>1;
build(u<<1,l,mid),build(u<<1|1,mid+1,r);
}
}
void add(int u,int l,int r,int val){//区间修改最大值
if(l<=tr[u].l && tr[u].r<=r){
tr[u].val=max(tr[u].val,val);
return;
}
int mid=tr[u].l+tr[u].r>>1;
if(l<=mid)add(u<<1,l,r,val);
if(r>mid)add(u<<1|1,l,r,val);
}
int query(int u,int x){//单点查询
if(tr[u].l==tr[u].r){
return tr[u].val;
}
pushdown(u);
int mid=tr[u].l+tr[u].r>>1;
if(x<=mid)return query(u<<1,x);
else return query(u<<1|1,x);
}
int main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
//输入
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
cin>>f[i].l>>f[i].r>>f[i].w;
}
//建树,预处理最大值
build(1,1,m);
for(int i=1;i<=n;i++){
if(f[i].r+1-tr[i].l>=k){
add(1,f[i].l,f[i].r+1-k,f[i].w);
}
}
//dp求值
for(int i=k;i<=m;i++){
dp[i]=max(dp[i-1],dp[i-k]+query(1,i-k+1));
}
cout<<dp[m];
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...