<二分||线段树>【noip 2012】codevs 1217 借教室

来源:互联网 发布:微氪网络监控一体机 编辑:程序博客网 时间:2024/05/29 14:23

这就是个题面
两种做法啊,二分和线段树
一.二分+前缀和:
从第一天到第n天,一天一天地算,然后二分找有没有不符合的,虽然很暴力,但是可以做啊QAQ
代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=1000000+10;int n,m;int rr[maxn],cha[maxn],d[maxn],t[maxn],s[maxn];bool check(int x){    //printf("*%d\n",x);    memset(cha,0,sizeof(cha));    for(int i=1;i<=x;++i)    {        cha[s[i]]+=d[i];        cha[t[i]+1]-=d[i];    }    int sum=0;    for(int i=1;i<=n;++i)    {        sum+=cha[i];        if(sum>rr[i]) return false;    }    return true;}int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=n;++i) scanf("%d",&rr[i]);    for(int i=1;i<=m;++i) scanf("%d%d%d",&d[i],&s[i],&t[i]);    int l=1,r=m;    while(l+1<r)    {        int mid=(l+r)>>1;        if(check(mid)) l=mid;        else r=mid;    }    int ans;    if(!check(l)) ans=l;    else ans=r;    if(r==m&&check(r)) printf("0");    else     {        printf("-1\n");        printf("%d",ans);    }    return 0;}

二.线段树
维护区间最小值,每次修改区间,查询是否有最小值小于零
一开始TLE,发现是询问最小值是,不用再写一个ask函数来询问刚刚修改的区间的最小值,而是直接O(1)询问区间1~n的最小值就可以了2333(感觉自己好智障)
代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=1e6+10,inf=0xfffffff;int n,m,ans;int rr[maxn];struct hh{    int l,r;    int minn;    int lazy;}tree[maxn<<2];void spread(int i){    int &x=tree[i].lazy;    if(x)    {        tree[i<<1].minn+=x;        tree[i<<1|1].minn+=x;        tree[i<<1].lazy+=x;        tree[i<<1|1].lazy+=x;        x=0;    }}void add(int l,int r,int x,int i){    int lx=tree[i].l,rx=tree[i].r;    if(lx>=l&&rx<=r)    {        tree[i].lazy-=x;        tree[i].minn-=x;        return;    }    spread(i);     int mid=(lx+rx)>>1;    if(l<=mid) add(l,r,x,i<<1);    if(r>mid) add(l,r,x,i<<1|1);    tree[i].minn=min(tree[i<<1].minn,tree[i<<1|1].minn);}void build(int l,int r,int i){    tree[i].l=l;    tree[i].r=r;    if(l==r)    {        tree[i].minn=rr[l];        return ;    }    int mid=(l+r)>>1;    build(l,mid,i<<1);    build(mid+1,r,i<<1|1);    tree[i].minn=min(tree[i<<1].minn,tree[i<<1|1].minn);}int main(){    memset(tree,0,sizeof(tree));    scanf("%d%d",&n,&m);    for(int i=1;i<=n;++i) scanf("%d",&rr[i]);    build(1,n,1);    for(int i=1;i<=m;++i)    {        int d,s,t;        scanf("%d%d%d",&d,&s,&t);        add(s,t,d,1);        if(tree[1].minn<0)        {            ans=i;            break;        }    }    if(ans) printf("-1\n");    printf("%d",ans);    return 0;}
原创粉丝点击