这里提出第三种(应该是)毒瘤做法
考虑我们把书标上等级,也就是 (b_i)
等级为 (b_i) 的书可以放在 (0-b_i) 这个区间中
那么我们直接贪心,先放大的再放小的,尽量的向右区间放置
直接用线段树维护哪些地方可以放就行了(坐稳最差解
#define __AVX__ 1
#define __AVX2__ 1
#define __SSE__ 1
#define __SSE2__ 1
#define __SSE2_MATH__ 1
#define __SSE3__ 1
#define __SSE4_1__ 1
#define __SSE4_2__ 1
#define __SSE_MATH__ 1
#define __SSSE3__ 1
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
#include <immintrin.h>
#include <emmintrin.h>
#include <cstdio>
#include <algorithm>
using namespace std;
struct point
{
long long a,b;
}p[1000010];
struct segment
{
int minid;
}tree[1000010<<2];
bool cmp(point a,point b)
{
return a.a>b.a;
}
int n;
long long pl[1000010],ans;
void build(int u,int l,int r)
{
tree[u].minid=r;
if(l==r) return ;
int mid=(l+r)>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
}
void change(int u,int l,int r,int p)
{
if(l==r)
{
tree[u].minid=p;
return ;
}
int mid=(l+r)>>1;
if(p<=mid) change(u<<1,l,mid,p);
if(p>mid) change(u<<1|1,mid+1,r,p);
if(pl[tree[u<<1].minid]<pl[tree[u<<1|1].minid]) tree[u].minid=tree[u<<1].minid;
else tree[u].minid=tree[u<<1|1].minid;
}
int find(int u,int l,int r,int x,int y)
{
if(x<=l&&r<=y) return tree[u].minid;
int mid=(l+r)>>1,ans1=-10,ans2=-10;
if(x<=mid) ans1=find(u<<1,l,mid,x,y);
if(y>mid) ans2=find(u<<1|1,mid+1,r,x,y);
if(ans1==-10||ans2==-10) return max(ans1,ans2);
if(pl[ans1]<pl[ans2]) return ans1;
else return ans2;
}
int main()
{
tree[1].minid=0;
scanf("%d",&n);
build(1,0,n);
for(int i=1;i<=n;i++) scanf("%lld",&p[i].a),p[i].a;
for(int i=1;i<=n;i++) scanf("%lld",&p[i].b),p[i].b;
sort(p+1,p+n+1,cmp);
for(int i=1;i<=n;i++)
{
int now=find(1,0,n,0,p[i].b);
if(p[i].a>pl[now])
{
pl[now]=p[i].a;
change(1,0,n,now);
}
}
for(int i=0;i<=n;i++) ans+=pl[i];
printf("%lld",ans%910666);
}