BZOJ4977: [Lydsy1708月赛]跳伞求生(线段树)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35649707/article/details/82758625

传送门

题解:

只能说出题人的脑洞是真的大。。

a a b b 一起排序,合法的序列是一个括号序列,我们贪心的维护这个括号序列的合法性即可。 可用线段树优化至 O ( n log n ) O(n \log n)

#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';
}

猜你喜欢

转载自blog.csdn.net/qq_35649707/article/details/82758625
今日推荐