版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35649707/article/details/82758625
题解:
只能说出题人的脑洞是真的大。。
把 和 一起排序,合法的序列是一个括号序列,我们贪心的维护这个括号序列的合法性即可。 可用线段树优化至 。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair <int,int> pii;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-') f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=2e5+50, INF=0x3f3f3f3f;
int n,m,tot;
pii mx[N*4];
set <int> lbr;
int rbr[N];
struct data {
int x,w,val;
friend inline bool operator <(const data &a,const data &b) {return a.w<b.w || (a.w==b.w && !a.x);}
} c[N];
inline void build(int k,int l,int r) {
if(l==r) {mx[k]=pii((c[l].x ? c[l].val : -INF),l); return;}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
mx[k]=max(mx[k<<1],mx[k<<1|1]);
}
inline pii ask(int k,int l,int r,int L,int R) {
if(L<=l && r<=R) return mx[k];
int mid=(l+r)>>1;
if(R<=mid) return ask(k<<1,l,mid,L,R);
else if(L>mid) return ask(k<<1|1,mid+1,r,L,R);
else return max(ask(k<<1,l,mid,L,R),ask(k<<1|1,mid+1,r,L,R));
}
inline void inc(int k,int l,int r,int p) {
if(l==r) {mx[k].first=-INF; return;}
int mid=(l+r)>>1;
if(p<=mid) inc(k<<1,l,mid,p);
else inc(k<<1|1,mid+1,r,p);
mx[k]=max(mx[k<<1],mx[k<<1|1]);
}
int main() {
n=rd(), m=rd(), tot=n+m;
for(int i=1;i<=n;i++) c[i].x=0, c[i].w=rd();
for(int i=n+1;i<=tot;i++) c[i].x=1, c[i].w=rd(), c[i].val=rd()-c[i].w;
sort(c+1,c+tot+1); build(1,1,tot);
LL ans=0;
for(int i=tot;i>=1;i--) {
if(!c[i].x) {
int r=lbr.size() ? *--lbr.end() : i;
lbr.insert(i);
pii mx=ask(1,1,tot,1,r);
if(mx.first+c[i].w<0) break;
else {
ans+=mx.first+c[i].w;
if(mx.second<i) rbr[mx.second]=1;
else lbr.erase(lbr.upper_bound(mx.second));
inc(1,1,tot,mx.second);
}
} else if(rbr[i]) lbr.erase(lbr.begin());
} cout<<ans<<'\n';
}