P1083 借教室

传送门

思路:

  ① 45 分的暴力很好写:只要按每个人借教室的要求,将数组不停地减,如果有一个数小于 0 ,直接停止输出就行了。

   (正解好像是用二分)线段树做法: 其实跟暴力几乎一样,主要利用的是线段树的标记下传来优化常数,(第一次线段标记下传写错了只得5分。。。)其次只要用线段树维护区间的最小值,判一判是否有负数,就A了。

标程:

① 暴力判断:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdlib>
#include<queue>
#include<vector>
#include<deque>
#include<stack>
#include<map>
#include<set>
using namespace std;
#define maxn 2000500
long long sum[maxn];
long long n,m;
inline long long read()
{
    long long kr=1,xs=0;
    char ls;
    ls=getchar();
    while(!isdigit(ls))
    {
        if(!(lc^45))
        kr=-1;
        ls=getchar();
    }
    while(isdigit(ls))
    {
        xs=(xs<<1)+(xs<<3)+(ls^48);
        ls=getchar();
    }
    return kr*xs;
}
int main()
{
    memset(sum,0,sizeof(sum));
    n=read();m=read();
    for(long long i=1;i<=n;i++)
    {
        sum[i]=read();
    }
    long long dj,sj,tj;
    for(long long i=1;i<=m;i++)
    {
        dj=read();sj=read();tj=read();
        for(long long j=sj;j<=tj;j++)
        {
            sum[j]-=dj;
            if(sum[j]<0)
            {
                printf("-1\n%lld\n",i);
                return 0;
            }
        }
    }
    printf("0\n");
return 0;
}

② 线段树

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdlib>
#include<queue>
#include<vector>
#include<deque>
#include<stack>
#include<map>
#include<set>
using namespace std;
#define maxn 2005000
int sum[maxn<<2],add[maxn<<2];
int n,m,a[maxn];
inline int read()
{
    int kr=1,xs=0;
    char ls;
    ls=getchar();
    while(!isdigit(ls))
    {
        if(!(ls^45))
            kr=-1;
        ls=getchar();
    }
    while(isdigit(ls))
    {
        xs=(xs<<1)+(xs<<3)+(ls^48);
        ls=getchar();
    }
    return xs*kr;
}
inline int lck(int xz,int xa)
{
    return xz<xa?xz:xa;
}
inline void build_sum(int k,int l,int r)
{
    if(l==r)
    {
        sum[k]=a[l];
        return;
    }
    int mid=l+r>>1;
    build_sum(k<<1,l,mid);
    build_sum(k<<1|1,mid+1,r);
    sum[k]=lck(sum[k<<1],sum[k<<1|1]);
}
inline void push_up(int k)
{
    sum[k]=lck(sum[k],lck(sum[k<<1]-add[k<<1],sum[k<<1|1]-add[k<<1|1]));
}
inline void push_down(int k)
{
    add[k<<1]+=add[k];
    add[k<<1|1]+=add[k];
    add[k]=0;
}
inline void change(int k,int l,int r,int x,int y,int w)
{
    if(x==l&&r==y)
    {
        sum[k]-=add[k]+w;
        if(l!=r)
        {
            add[k<<1]+=add[k]+w;
            add[k<<1|1]+=add[k]+w;
        }
        add[k]=0;
        return;
    }
    push_down(k);
    int mid=l+r>>1;
    if(y<=mid)change(k<<1,l,mid,x,y,w);
    else if(mid<x)change(k<<1|1,mid+1,r,x,y,w);
    else
    {
        change(k<<1,l,mid,x,mid,w);
        change(k<<1|1,mid+1,r,mid+1,y,w);
    }
    push_up(k);
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++)
        a[i]=read();
    build_sum(1,1,n);
    bool flag=true;
    for(int i=1;i<=m;i++)
    {
        int dj,sj,tj;
        dj=read();sj=read();tj=read();
        change(1,1,n,sj,tj,dj);
        if(sum[1]<0)
        {
            printf("-1\n%d\n",i);
            return 0;
        }
    }
    printf("0\n");
return 0;
}

 

posted @ 2018-09-24 21:38  落笔映惆怅丶  阅读(163)  评论(0编辑  收藏  举报