洛谷p1083借教室

今天用线段树把这个题又做了一遍,除了代码有点长其他还好,线段树思维不难

先读入每天提供的教室数,在建树,依次读入每个人的要求,先区间修改,再判断是否合法(注意修改时要变为负数,因为是减去当前值)判断合法直接用tree[1]即可

#include<bits/stdc++.h>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define maxn 1000001
using namespace std;
 
inline int read(){
    int x=0,f=1;char c=getchar();
    while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
    return x*f;
}
 
int n,m,aa[maxn],tree[maxn<<2],lazy[maxn<<2];
 
bool ok=1;
 
void pushup(int rt){
    tree[rt]=min(tree[rt<<1],tree[rt<<1|1]);
}
 
void buildtree(int l,int r,int rt){
    if(l==r){
        tree[rt]=aa[l];return;
    }
    int mid=(l+r)>>1;
    buildtree(lson);
    buildtree(rson);
    pushup(rt);
}
 
void add(int l,int r,int rt,int delta){
    lazy[rt]+=delta;
    tree[rt]+=delta;
}
 
void pushdown(int l,int r,int rt){
    if(!lazy[rt]) return;
    int mid=(l+r)>>1;
    add(lson,lazy[rt]);
    add(rson,lazy[rt]);
    lazy[rt]=0;
}
 
void xg(int L,int R,int delta,int l,int r,int rt){
    if(L<=l&&R>=r){
        add(l,r,rt,delta);return ;
    }
    pushdown(l,r,rt);
    int mid=(l+r)>>1;
    if(L<=mid)xg(L,R,delta,lson);
    if(R>mid)xg(L,R,delta,rson);
    pushup(rt);
}
 
int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++){
        aa[i]=read();
    }
    buildtree(1,n,1);
    for(int i=1;i<=m;i++){
        int d=read(),s=read(),t=read();
        xg(s,t,-d,1,n,1);
        if(tree[1]<0) {printf("-1\n%d",i);return 0;
        }
    }
    printf("0");return 0;
}

当然还有其他方法,就是我原来时做的(当时线段树基本不会)

总的来说就是差分+二分(应该叫差分吧,不管了,应该没啥影响)

先将每个数据存起来,判断是否全都可行,就是把m带入计算,用cf记录差分,操作为:cf[s[i]]+=d[i];cf[t[i]+1]-=d[i];在用need存每天总共所需的need[i]=need[i]+cf[i](妙啊

如果m不行的话就开始二分,没什么好说的了,上代码

#include<bits/stdc++.h>
#define maxm 1000010
using namespace std;

int d[maxm],s[maxm],t[maxm],r[maxm],cf[maxm],need[maxm],lef=1,rit,n,m;

inline int read()
{
    int f=1,x=0;char ch=getchar();
    while(ch>'9'||ch<'0') {if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    return f*x;
} 

bool work(int x)
{
    memset(cf,0,sizeof(cf));
    for(int i=1;i<=x;i++)
    {
        cf[s[i]]+=d[i];
        cf[t[i]+1]-=d[i];
    }
    for(int i=1;i<=n;i++)
    {
        need[i]=need[i-1]+cf[i];
        if(need[i]>r[i]) return 0;
    }
    return 1;
}

int main()
{
    n=read();m=read();for(int i=1;i<=n;i++) r[i]=read();
    for(int i=1;i<=m;i++)
    {
        d[i]=read();s[i]=read();t[i]=read();
    }
    rit=m;
    if(work(m)) {printf("0");return 0;}
    while(lef<=rit)
    {
        int mid=(lef+rit)>>1;
        if(work(mid)) lef=mid+1;
        else rit=mid-1;
    }
    printf("-1\n%d",lef);
    return 0;
} 

猜你喜欢

转载自www.cnblogs.com/plysc/p/10333128.html
今日推荐