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; }