1041D-Glider (Pensamiento + Dicotomía + Suma de prefijo)

https://codeforces.com/problemset/problem/1041/D


Ideas:

Se puede encontrar que el punto de partida seleccionado no debe ser peor en el extremo izquierdo de un determinado intervalo de segmento de línea.

Entonces On enumera el punto de partida y encuentra rápidamente el intervalo donde está el punto final. El proceso descendente satisface la monotonicidad, por lo que el intervalo donde la ubicación final es la dicotomía. La verificación del medio puede ser O1check acumulando la diferencia entre el prefijo y el intervalo de procesamiento.

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=2e5+1000;
typedef long long LL;
inline LL read(){LL x=0,f=1;char ch=getchar();	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
struct P{
  LL l,r;
}a[maxn];
LL sum[maxn];
bool check(LL p,LL q,LL n,LL h){

    LL downdis=sum[q]-sum[p];
   /// cout<<"p="<<p<<" "<<"q="<<q<<" "<<"downdis="<<downdis<<"\n";
    if(h-downdis>0) return true;
    else return false;
}
int main(void)
{
  cin.tie(0);std::ios::sync_with_stdio(false);
  LL n,h;cin>>n>>h;
  for(LL i=1;i<=n;i++){
    cin>>a[i].l>>a[i].r;
  }
  sum[1]=0;
  for(LL i=2;i<=n;i++){
    sum[i]=sum[i-1]+(a[i].l-a[i-1].r);
  }
  LL ans=0;
  for(LL i=1;i<=n;i++){///枚举起点,处于某个线段区间的左端点
      LL l=i;LL r=n;
      while(l<r){
          LL mid=(l+r+1)>>1;
          if(check(i,mid,n,h)) l=mid;
          else r=mid-1;
      }
     /// cout<<"i="<<i<<" "<<"l="<<l<<"\n";
      LL res1=a[l].r-a[i].l;
      LL temp=h;
      temp-=(sum[l]-sum[i]);
      res1+=temp;
      ans=max(ans,res1);
  }
  cout<<ans<<"\n";
return 0;
}

 

Supongo que te gusta

Origin blog.csdn.net/zstuyyyyccccbbbb/article/details/115266104
Recomendado
Clasificación