1. 程式人生 > >【NOIP2012 提高組 day2】借教室

【NOIP2012 提高組 day2】借教室

題目

這裡寫圖片描述這裡寫圖片描述

題解

–首先,這道題用線段樹是可以過得,luogu上最慢的點也才700ms,具體就不說了
主要講更快的二分加差分的方法
–首先,差分是一種對區間修改的優化,可以把時間複雜度降到只跑一遍
重點是二分,因為對於某個點,如果不滿足,那麼不滿足的點一定是它,或是它的前方的某個點
如果滿足,那就一定在後面
其實是單調的
就可以用二分來做

程式碼

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm> using namespace std; const int MAXN=1e6+5; int n,m; int r[MAXN]; int d[MAXN],s[MAXN],t[MAXN]; int cf[MAXN]; bool ok(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++){ cf[i]+=cf[i-1
]; if(cf[i]>r[i]) return 0; } return 1; } int main(){ // freopen("classroom.in","r",stdin); // freopen("classroom.out","w",stdout); cin>>n>>m; for(int i=1;i<=n;i++) scanf("%d",&r[i]); for(int i=1;i<=m;i++) scanf("%d%d%d",&d[i],&s[i],&t[i]); if
(ok(m)){ cout<<0; return 0; } int L=1,R=m; while(L<R){ int mid=(L+R)/2; if(ok(mid)) L=mid+1; else R=mid; } cout<<-1<<endl<<R; return 0; }