今天用线段树把这个题又做了一遍,除了代码有点长其他还好,线段树思维不难
先读入每天提供的教室数,在建树,依次读入每个人的要求,先区间修改,再判断是否合法(注意修改时要变为负数,因为是减去当前值)判断合法直接用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 %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 %d",lef); return 0; }