https://ac.nowcoder.com/acm/contest/7502/H
学习自
https://blog.csdn.net/qq_30361651/article/details/109477637
无论是分治还是单调队列搞二分都是O(w m logm)的,叉姐题解说的SMAWK算法中文网上都查不到相关的题解或者算法笔记,维基百科上倒是有。。。还是不学了,这个时限也是放log过的
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=2e5+10;
const ll inf=1ll<<61;
int n,m;
ll f[maxl],sum[maxl],g[maxl],ng[maxl];
vector<int> a[maxl];
inline void prework()
{
for(int i=1;i<=100;i++)
a[i].clear();
for(int i=0;i<=m;i++)
f[i]=0;
for(int i=1;i<=n;i++)
{
int w,v;scanf("%d%d",&w,&v);
a[w].push_back(v);
}
}
inline void dp(int len,int l,int r,int l1,int r1)
{
ll mx=-inf;
int id=0,mid=(l+r)>>1;
for(int i=max(l1,mid-len);i<=min(r1,mid);i++)
if(mx<g[i]+sum[mid-i])
mx=g[i]+sum[mid-i],id=i;
ng[mid]=mx;
if(l<=mid-1)
dp(len,l,mid-1,l1,id);
if(mid+1<=r)
dp(len,mid+1,r,id,r1);
}
inline bool cmp(const int &x,const int &y){return x>y;}
inline void solv(int x)
{
int l=a[x].size();
if(!l)
return;
sort(a[x].begin(),a[x].end(),cmp);
for(int i=1;i<=l;i++)
sum[i]=sum[i-1]+a[x][i-1];
for(int i=0;i<x;i++)
{
int tp=0;
for(int j=i,k=1;j<=m;j+=x,k++)
g[k]=f[j],tp=k;
g[0]=0;
dp(l,1,tp,1,tp);
for(int j=i,k=1;j<=m;j+=x,k++)
f[j]=ng[k];
}
}
inline void mainwork()
{
for(int i=1;i<=100;i++)
solv(i);
}
inline void print()
{
ll ans=0;
for(int i=1;i<=m;i++) ans=max(ans,f[i]);
printf("%lld\n",ans);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
prework();
mainwork();
print();
}
return 0;
}