【AT2645】Exhausted?

题面

$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\n",-ans);
}

猜你喜欢

转载自www.cnblogs.com/shxnb666/p/11426763.html