题面
$zhhx$讲过的题,拓展霍尔定理。
题解
考虑一个区间$[1..l]$,找到让它最紧张的$[r..n]$,这个操作我们用线段树实现,因为$r$越往左越宽裕,所以在一开始的时候,是一个递减的等差数列的形式。
然后线段树区间修改求最小值。
代码$WA$了几个点,应该是有点小锅的。要是有大佬看出来的记得说一下w。
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #define N 200050 #define ri register int #define INF 10000007 using namespace std; int n,m; struct node { int l,r; bool operator < (const node &rhs) const { return l<rhs.l; } } a[N]; int b[N]; struct segment_tree{ int tt[N<<2],tag[N<<2]; void maketree(int x,int lb,int rb) { if (lb==rb) { tt[x]=b[lb]; tag[x]=0; return; } int mid=(lb+rb)/2; maketree(2*x,lb,mid); maketree(2*x+1,mid+1,rb); tt[x]=min(tt[2*x],tt[2*x+1]); } void pushdown(int x) { int k=tag[x]; tag[x]=0; tt[2*x]+=k; tag[2*x]+=k; tt[2*x+1]+=k; tag[2*x+1]+=k; } void add(int x,int l,int r,int k,int lb,int rb) { if (l<=lb && rb<=r) { tt[x]+=k; tag[x]+=k; return; } if (lb>r || rb<l) return; pushdown(x); int mid=(lb+rb)/2; add(2*x,l,r,k,lb,mid); add(2*x+1,l,r,k,mid+1,rb); tt[x]=min(tt[2*x],tt[2*x+1]); } int query(int x,int l,int r,int lb,int rb) { if (l<=lb && rb<=r) { return tt[x]; } if (lb>r || rb<l) return INF; pushdown(x); int mid=(lb+rb)/2; return min(query(2*x,l,r,lb,mid),query(2*x+1,l,r,mid+1,rb)); } } yy; int main() { scanf("%d %d",&m,&n); for (ri i=1;i<=m;i++) scanf("%d %d",&a[i].l,&a[i].r); sort(a+1,a+m+1); int cnt=0; for (ri i=n+1;i>=1;i--) b[i]=cnt++; yy.maketree(1,1,n+1); int ans=0; for (ri i=1;i<=m;i++) { yy.add(1,1,a[i].r,-1,1,n+1); int ming=yy.query(1,a[i].l+1,n+1,1,n+1); if (a[i].l+ming<ans) ans=a[i].l+ming; } printf("%d ",-ans); }