[NOIP2012提高組]借教室
阿新 • • 發佈:2017-09-15
cnblogs chang pri 最小 sin logs pre urn git
題目:洛谷P1083、Vijos P1782、codevs1217。
題目大意:有n天,每天可以借a[i]個教室。有m個請求,每個請求要在一段連續天數內借固定數目的教室。請求只能按順序批準。求第一個無法批準的請求是第幾個請求,或全部可以批準。
解題思路:看到區間,容易想到線段樹維護(正解貌似是二分,燃鵝我只能理解線段樹啊~)。這裏顯然只需維護最小值。不過如果姿勢不好,可是會T的喲。
線段樹肯定很好寫,但想不超時,就得優化。例如讀入優化、標記永久化、遞歸過程能用全局變量用全局變量、搜到答案直接退出等。最後提交,坐等AC即可。
C++ Code:
#include<cstdio> #include<cstdlib> #include<cctype> using namespace std; long long d[4000005],p[4000005]; int i,n,m,L,R,k; inline long long min(long long a,long long b){return(a<b)?a:b;} inline int readint(){ char c=getchar(); int p=0; for(;!isdigit(c);c=getchar()); for(;isdigit(c);c=getchar())p=(p<<3)+(p<<1)+(c^‘0‘); return p; } void make_tree(int l,int r,int o){ p[o]=0; if(l==r){ d[o]=readint(); return; } int mid=l+r>>1,lf=o<<1,rg=o<<1|1; make_tree(l,mid,lf); make_tree(mid+1,r,rg); d[o]=min(d[lf],d[rg]); } void change(int l,int r,int o){ if(L<=l&&r<=R){ p[o]+=k; if(d[o]-p[o]<0){ printf("-1\n%d\n",i); exit(0); } return; } int mid=l+r>>1,lf=o<<1,rg=o<<1|1; if(L<=mid)change(l,mid,lf); if(mid<R)change(mid+1,r,rg); d[o]=min(d[lf]-p[lf],d[rg]-p[rg]); if(d[o]-p[o]<0){ printf("-1\n%d\n",i); exit(0); } } int main(){ n=readint(),m=readint(); make_tree(1,n,1); for(i=1;i<=m;++i){ k=readint(),L=readint(),R=readint(); change(1,n,1); } puts("0"); return 0; }
[NOIP2012提高組]借教室