[CF542A]Place Your Ad Here

[CF542A]Place Your Ad Here

题目大意:

\(n(n\le2\times10^5)\)个广告和\(m(m\le2\times10^5)\)个电视台,第\(i\)个广告只能在\([l_i,r_i]\)内播放,第\(j\)个电视台会在时间段\([a_j,b_j]\)播出,并且有\(c_j\)个人收看。选择第\(x\)个广告和第\(y\)个电视台的收益为\((v-u)c_y\),其中\([u,v]=[l_x,r_x]\cap[a_y,b_y]\)
从中选取一个广告和一个电视台,使收益最大。求最大收益,并输出任意一种方案。

思路:

将广告拆成两个端点排序,将电视台按照右端点排序。

枚举每个电视台\([l,r]\),若一个广告只有左端点在\(r\)前,那么我们只关心最左的左端点;若一个广告左右端点均在\([l,r]\)内,那么我们只关心其长度;若一个广告左端点在\(l\)前,右端点在\([l,r]\)内,那么我们只关心其右端点的位置。

对于第一种情况,用set维护即可;后两种情况只需用线段树维护区间最大值。

时间复杂度\(\mathcal O(n\log n)\)

源代码:

#include<set>
#include<cstdio>
#include<cctype>
#include<algorithm>
inline int getint() {
	register char ch;
	while(!isdigit(ch=getchar()));
	register int x=ch^'0';
	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
	return x;
}
typedef long long int64;
struct Node {
	int p,id;
	bool operator < (const Node &rhs) const {
		return p<rhs.p;
	}
};
struct Seg {
	int l,r,w,id;
	bool operator < (const Seg &rhs) const {
		return r<rhs.r;
	}
};
const int N=2e5+1,K=8e5+1;
Node a[N],b[N];
Seg c[N];
int rnk[N],tmp[K];
class SegmentTree {
	#define _left <<1
	#define _right <<1|1
	#define mid ((b+e)>>1)
	private:
		std::pair<int,int> val[K<<2];
		void push_up(const int &p) {
			val[p]=std::max(val[p _left],val[p _right]);
		}
	public:
		void modify(const int &p,const int &b,const int &e,const int &x,const std::pair<int,int> &v) {
			if(b==e) {
				val[p]=std::max(val[p],v);
				return;
			}
			if(x<=mid) modify(p _left,b,mid,x,v);
			if(x>mid) modify(p _right,mid+1,e,x,v);
			push_up(p);
		}
		std::pair<int,int> query(const int &p,const int &b,const int &e,const int &l,const int &r) const {
			if(b==l&&e==r) return val[p];
			std::pair<int,int> ret(0,0);
			if(l<=mid) ret=std::max(ret,query(p _left,b,mid,l,std::min(mid,r)));
			if(r>mid) ret=std::max(ret,query(p _right,mid+1,e,std::max(mid+1,l),r));
			return ret;
		}
	#undef _left
	#undef _right
	#undef mid
};
SegmentTree t1,t2;
std::set<std::pair<int,int> > set;
int main() {
	const int n=getint(),m=getint();
	int tot=0;
	for(register int i=1;i<=n;i++) {
		const int l=getint(),r=getint();
		a[i]=(Node){l,i};
		b[i]=(Node){r,i};
		tmp[++tot]=l;
		tmp[++tot]=r;
	}
	for(register int i=1;i<=m;i++) {
		tmp[++tot]=c[i].l=getint();
		tmp[++tot]=c[i].r=getint();
		c[i].w=getint();
		c[i].id=i;
	}
	std::sort(&tmp[1],&tmp[tot]+1);
	for(register int i=1;i<=n;i++) {
		a[i].p=std::lower_bound(&tmp[1],&tmp[tot]+1,a[i].p)-tmp;
		b[i].p=std::lower_bound(&tmp[1],&tmp[tot]+1,b[i].p)-tmp;
	}
	for(register int i=1;i<=m;i++) {
		c[i].l=std::lower_bound(&tmp[1],&tmp[tot]+1,c[i].l)-tmp;
		c[i].r=std::lower_bound(&tmp[1],&tmp[tot]+1,c[i].r)-tmp;
	}
	std::sort(&a[1],&a[n]+1);
	std::sort(&b[1],&b[n]+1);
	std::sort(&c[1],&c[m]+1);
	for(register int i=1;i<=n;i++) {
		rnk[a[i].id]=i;
	}
	int64 ans=0;
	int x,y;
	for(register int i=1,j=1,k=1;i<=m;i++) {
		for(;j<=n&&a[j].p<=c[i].r;j++) {
			set.insert(std::make_pair(tmp[a[j].p],a[j].id));
		}
		for(;k<=n&&b[k].p<=c[i].r;k++) {
			const int j=rnk[b[k].id];
			set.erase({tmp[a[j].p],a[j].id});
			t1.modify(1,1,tot,a[j].p,{tmp[b[k].p]-tmp[a[j].p],a[j].id});
			t2.modify(1,1,tot,a[j].p,{tmp[b[k].p],a[j].id});
		}
		//-: ad
		//=: tv
		int len=0,z=0;
		if(!set.empty()) {
			//  ------
			//======
			const int t=tmp[c[i].r]-std::max(tmp[c[i].l],set.begin()->first);
			if(t>len) {
				len=t;
				z=set.begin()->second;
			}
		}
		{
			//  --
			//======
			const auto p=t1.query(1,1,tot,c[i].l,c[i].r);
			if(p.first>len) {
				len=p.first;
				z=p.second;
			}
		}
		{
			//------
			//  ======
			const auto p=t2.query(1,1,tot,1,c[i].l);
			if(p.first-tmp[c[i].l]>len) {
				len=p.first-tmp[c[i].l];
				z=p.second;
			}
		}
		if(1ll*len*c[i].w>ans) {
			ans=1ll*len*c[i].w;
			x=z,y=c[i].id;
		}
	}
	printf("%lld\n",ans);
	if(ans) printf("%d %d\n",x,y);
	return 0;
}
posted @ 2019-01-04 08:20  skylee03  阅读(445)  评论(0编辑  收藏  举报