首页 > 其他分享 >题解 LOJ P2393 「JOISC 2017 Day 2」门票安排

题解 LOJ P2393 「JOISC 2017 Day 2」门票安排

时间:2023-02-25 09:00:10浏览次数:33  
标签:std cnt P2393 LOJ 题解 mid int 反转 区间

题意

咕咕咕。

题解

这题太神了,无限膜拜 p_b_p_b,搬运一波题解。

首先考虑二分。题意等价于选一些区间进行反转。首先注意到反转的区间两两有交,不然不反转一定更优。设反转的区间交为 \([x,y]\),反转前后位置 \(i\) 被覆盖的次数分别为 \(a_i,b_i\)。设 \(t\) 表示 \([x,y]\) 中 \(b\) 最大的位置,那么「容易」观察到:

  • 存在最优方案使得 \(b_t \geq \max\{b_x\}-1\)

    如果不,考虑取消反转一个 \(l=x\) 的区间和 \(r=y\) 的区间,只有 \([x,y]\) 中的 \(b\) 会增加,因此对答案不劣。

  • 存在最优方案使得 \(a_t = \max\{a_x\}\)

    如果 \(a_t\) 不是最大的,那么最大值 \(a_k\) 一定满足 \(k \notin [x,y]\),否则 \(b_t\) 不是 \([x,y]\) 中最大的。因此至少一个被反转的区间没有覆盖到 \(k\),于是 \(a_k - b_k \leq a_t - b_t - 1\),化简得到 \(b_k - b_t \geq 2\),与上一条矛盾。

  • 存在最优方案使得所有 \(\max\{a_x\}\) 都满足 \(x \in [x,y]\)

    同上。

因此我们可以找到 \(t\) 的位置,然后分类讨论 \(b_t\) 是 \(\max\{b_x\}-1\) 还是取到了 \(\max\{a_x\}\)。

注意到我们二分了答案 \(mid\),那么有 \(mid = b_t = a_t - cnt\),或者 \(mid -1 = b_t = a_t - cnt\),化简得 \(cnt = a_t - mid (+1)\),其中 \(cnt\) 是反转的区间个数。

于是我们对于二分的答案 \(mid\),分别检查反转区间个数为 \(a_t - mid\) 和 \(a_t - mid + 1\) 时是否合法即可。考虑如何判断:因为要反转的所有区间均跨过 \(t\),我们不妨找出这些区间,根据左端点从 \(1\) 到 \(t\) 扫,因为我们知道总的反转区间数,于是可以顺便计算出当前还要反转的区间个数 \(cnt'\) 和已经反转了的区间个数 \(q\)。如果 \(a_i - q + cnt' > mid\),那么位置 \(i\) 不合法,需要反转 \(\dfrac 12 (a_i - q + cnt')\) (上取整)个区间,因为 \(q\) 每增加 \(1\),\(cnt'\) 就减少 \(1\)。如果没有足够的区间用来反转,那么不合法。否则我们贪心地选择右端点最大的区间进行反转,对后面的影响更小。

# include <bits/stdc++.h>
# define fir first
# define sec second

const int N=200010,INF=0x3f3f3f3f;

typedef long long ll;

int n,m;
int a[N],b[N],c[N];

ll v[N];
int mx;
typedef std::pair <int,int> pil;

std::vector <pil> seg[N];
std::priority_queue <pil> cur;

ll d[N];

inline int read(void){
	int res,f=1;
	char c;
	while((c=getchar())<'0'||c>'9')
		if(c=='-')f=-1;
	res=c-48;
	while((c=getchar())>='0'&&c<='9')
		res=res*10+c-48;
	return res*f;
}
inline bool check(ll lim,ll cnt){
	std::fill(d+1,d+1+n,0);
	while(!cur.empty()) cur.pop();
	ll reved=0;
	for(int i=1;i<=mx;++i){
		for(auto v:seg[i]) cur.push(v);
		while(v[i]-reved+cnt>lim){
			if(cur.empty()) return false;
			pil c=cur.top();
			cur.pop();
			ll crev=std::min(1ll*c.sec,(v[i]-reved+cnt-lim+1)/2);
			reved+=crev,cnt-=crev,d[mx+1]-=crev,d[c.fir]+=2*crev;
			
			if(crev<c.sec) cur.push(std::make_pair(c.fir,c.sec-crev));
		}
	}
	
	for(int i=mx+1;i<=n;++i){
		d[i]+=d[i-1];
		if(d[i]+v[i]>lim) return false;
	}
	
	return true;
}

int main(void){
	n=read(),m=read();
	for(int i=1;i<=m;++i){
		a[i]=read(),b[i]=read(),c[i]=read();
		if(a[i]>b[i]) std::swap(a[i],b[i]);
		v[a[i]]+=c[i],v[b[i]]-=c[i];
	}
	for(int i=1;i<=n;++i) v[i]+=v[i-1];
	for(int i=1;i<=n;++i) if(v[mx]<v[i]) mx=i;
	for(int i=1;i<=m;++i) if(a[i]<=mx&&b[i]>mx) seg[a[i]].push_back(std::make_pair(b[i],c[i]));
	
	ll l=0,r=v[mx],ans=1e18;
	while(l<=r){
		ll mid=(l+r)>>1;
		if(check(mid,v[mx]-mid)||check(mid,v[mx]-mid+1)) ans=mid,r=mid-1;
		else l=mid+1;
	}
	printf("%lld",ans);
	
	return 0;
}

标签:std,cnt,P2393,LOJ,题解,mid,int,反转,区间
From: https://www.cnblogs.com/liuzongxin/p/17153743.html

相关文章

  • P8822 [传智杯#3 初赛] 课程报名 题解
    题目传送门题目大意有一种课程,初始定价为\(v\)元;每报名\(m\)个学员,课程的定价就要提升\(a\)元,一共有\(n\)个学员报名。解题思路因为一共有\(n\)个学员报名,所......
  • P8717 [蓝桥杯 2020 省 AB2] 成绩分析 题解
    题目传送门题目大意计算\(n\)个人考试的最高分、最低分和平均分。解题思路输入\(n\)个人成绩的同时,计算最大值,最小值和总数。再将总数除以\(n\)算出平均值并保......
  • AtCoder Beginner Contest 285 A-F 题解
    比赛链接A-EdgeChecker2判断y==2x||y==2x+1即可。点击查看代码#include<cstdio>#include<algorithm>#include<cstring>usingnamespacestd;inta......
  • AtCoder Beginner Contest 283 A-F 题解
    A-Power快速幂板子点击查看代码#include<cstdio>#include<algorithm>usingnamespacestd;#defineintlonglongintn,m;intqpow(inta,intb){ intr......
  • CF837D题解
    CF837D题解没有用的话今天晚上在CF题库里随便选题选的,感觉还不错的题。昨天就开始停自习了,但是一直在摆烂(悲,自从上个学期就这样了,非常怀念一年前的机房,风清气正,大家都......
  • THUPC2019 令人难以忘记的题目名称 题解
    首先感性感觉这个东西是比较有循环节的,但这是后话。最后几步一定是差分相同->每个数相同->全为0。不平凡地猜想差分\(k\)次全\(0\)等价于可以\(k\)步胜利。假设......
  • Universial Cup 题解
    开始瞎做题了全部都写了简要题意,题解默认折叠,可以来做做(?UniversialCup官网The1stUniversalCup比赛名称&题解链接题解包含题目QOJlinkCodeforcesGymLin......
  • loj2839
    除了L神txdy我还能说啥呢。(L神把这题搬模拟赛了。。。)即把每个x换成(或),问是否能通过不多于一次区间反转((与)交换)后合法。考虑怎样的括号串是合法的。假设......
  • 题解 北大集训2018 点分治
    题意给定\(n\)个点的树,求点分治方案数,对\(10^9+7\)取模。两种方案不同当且仅当点分树不同。\(1\leqn\leq5000\)题解考虑怎样合并两个点分治方案。如果我们有......
  • history 题解(并查集)
    考虑使用边带权并查集维护点之间的连通性,边权为这条边建立的时间,查询时如果查询时间小于边权则不能通行(巧妙地处理了时间的性质)。由于时间这种东西性质特殊无法路径压缩,所......