joig2022_e 题解

设计 fi 表示以第 i 个数结尾的选择的最大值。

fi=fj+aitypeitypej)。

发现可以选择的种类其实构成两段连续区间。

所以维护使得 typex=i 的所有 xfx 最大值。

这个用线段树可以很简洁的维护。

于是就 O(nlogn) 地做完了。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int inf = 1e18+7;
const int maxn=150010;
int dp[maxn];
int type[maxn],a[maxn],n,m,ans;
int tree[maxn*4];
void pushup(int x)
{
  tree[x]=max(tree[x*2],tree[x*2+1]);
}
void add(int now,int val,int l,int r,int x)
{
  if(l==r)
  {
    tree[x]+=val;
    return ;
  }
  int mid=(l+r)/2;
  if(now<=mid)
    add(now,val,l,mid,x*2);
  else
    add(now,val,mid+1,r,x*2+1);
  pushup(x);
  return ;
}
int question(int L,int R,int l,int r,int x)
{
  if(R>n||L<1||R<L)
    return 0;
  if(L<=l&&R>=r)
  {
    return tree[x];
  }
  int mid=(l+r)/2,res=-inf;
  if(L<=mid)
    res=max(res,question(L,R,l,mid,x*2));
  if(R>mid)
    res=max(res,question(L,R,mid+1,r,x*2+1));
  return res;
}
signed main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  for(int i=0;i<maxn*4;i++) tree[i]=-inf; 
  cin>>n>>m;
  for(int i=1;i<=n;i++)
    cin>>type[i]>>a[i];
  dp[1]=a[1];
  ans=max(ans,dp[1]);
  add(type[1],inf,1,m,1);
  add(type[1],a[1],1,m,1);
  for(int i=2;i<=n;i++)
  {
      dp[i]=max(question(1,type[i]-1,1,m,1),max(question(type[i]+1,m,1,m,1),0*1ll))+a[i];
      if(dp[i]>question(type[i],type[i],1,m,1))
      {
        int u=question(type[i],type[i],1,m,1);
        add(type[i],-u,1,m,1);
        add(type[i],dp[i],1,m,1);
      }
      ans=max(ans,dp[i]);
  }
  cout<<ans;
}
posted @   ChiFAN鸭  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示