NOIp2012 de explicaciones en el aula

Ver el título original ( https://www.luogu.org/problem/show?pid=1083 )
Esta pregunta es la primera vez que vi decisiva ah árbol segmento, pero el segundo día de la segunda línea de árboles NOIP preguntas de la prueba no lo haría píldoras pero bueno conocer la solución positiva es en realidad la mitad de la respuesta, si no se cree que el ah sala de examen, dos puntos, entonces primero hay que cumplir monótona, sabemos que el orden de la orden debe ser monótono, como este orden la mitad de la línea, pero un poco más simple es la piedra saltando NOIp2015, si no hay ningún pensamiento puede ir a ver esto - los billetes de avión ( http://blog.csdn.net/a1351937368/article/details/76473342 ) aquí en realidad debería ser un poco idea de que ( bajo las pegatinas de códigos, notas esencialmente importantes están escritos en el en el interior):

//二分 
#include<cstdio>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<stack>
#include<cmath>
using namespace std;

long long n,m,room[1001010],f[1010010],r[1001010];
struct node{
    int num,s,e;
}a[1001000];//num表示第i个订单需要教室个数,
//s(tart)为开始的日子,e(nd)为结束的日子 

inline int read(){
    int num;
    char ch;
    while((ch=getchar())<'0' || ch>'9');
    num=ch-'0';
    while((ch=getchar())>='0' && ch<='9'){
        num=num*10+ch-'0';
    }
    return num;
}
inline void out(int x){
    if(x>=10){
        out(x/10);
    }
    putchar(x%10+'0');
}
inline bool deal(int mid){
    //判断到第mid个订单是否会出现教室不够借的现象 
    memset(f,0,sizeof(f)),memset(r,0,sizeof(r));//初始化数组 
    for(register int i=1;i<=mid;i++){//一到mid的订单逐个枚举 
        f[a[i].s]-=a[i].num,f[a[i].e+1]+=a[i].num;//当前开始的减去当前订单需要的,结束的加上需要的 
        //用前缀和修改区间值 
    }
    for(register int i=1;i<=n;i++){
        f[i]+=f[i-1];//一维前缀和 
        if(room[i]+f[i]<0){//room[i]为第i天的教室个数,如果第i天需要的教室数加上拥有的教室数小于0 
            return true;//当前节点会出现教室不够用的情况 
        }
    }
    return false;//当前节点不会出现教室不够用的情况 
} 

int main(){
    n=read(),m=read();//天数和订单数量 
    for(register int i=1;i<=n;i++){
        room[i]=read();//第i天可用于租借的教室数量 
    }
    for(register int i=1;i<=m;i++){
        a[i].num=read(),a[i].s=read(),a[i].e=read();//租借数量,租借开始时间,租借结束时间 
    }
    int l=1,r=m,mid;//二分开始 
    while(l<r){
        mid=(l+r)/2;
        if(deal(mid)){//如果mid不满足
            r=mid;//如果当前的mid值不符合那么将右节点左移 
        }
        else{
            l=mid+1;//否则左节点右移 
        }
    }
    if(r==m){//说明没有出现教室不够用的情况 
        out(0);
    }
    else{
        printf("-1 \n"),out(r);
    }
    return 0;
}

Añadir un poco de optimización metafísica Esta pregunta se puede decir que correr muy rápido 20 puntos 2256ms pueden terminar el

Publicado 41 artículos originales · ganado elogios 58 · Vistas a 60000 +

Supongo que te gusta

Origin blog.csdn.net/a1351937368/article/details/78251770
Recomendado
Clasificación