題目:
2 2 6 08:00 09:00 5 08:59 09:59 2 6 08:00 09:00 5 09:00 10:00
11 6
轉換為RMQ問題,1天24h,1440min;a[i]表示第i分鐘的人數,n表示時間[t1,t2)之間來的人數,對這個區間內的a[i]+n,最後求的是a[i]的最大值。
解法1:模擬
#include#include #include using namespace std; #define clr(a) memset(a, 0, sizeof(a)) #define rep(i,s,t) for(int i = s; i <= t; ++i) #define per(i,s,t) for(int i = s; i >= t; --i) const int MAXN = 1450; int t, n, a[MAXN]; int main() { scanf("%d", &t); while(t--) { clr(a); scanf("%d", &n); int num, h1, m1, h2, m2; rep(i,0,n-1) { scanf("%d%d:%d%d:%d", &num, &h1, &m1, &h2, &m2); int s1 = h1 * 60 + m1, s2 = h2 * 60 + m2; rep(j,s1,s2-1) a[j] += num; } int ans = -1; rep(i,0,MAXN-1) ans = max(ans,a[i]); printf("%d\n", ans); } return 0; }
解法2:線段樹(ZKW)
#include#include #include using namespace std; #define clr(a) memset(a, 0, sizeof(a)) #define rep(i,s,t) for(int i = s; i <= t; ++i) #define per(i,s,t) for(int i = s, i >= t; --i) const int M = 1<<11, MAXN = 1440; int icase, n, a[M << 1]; void Add_x(int s, int t, int x) { int b = 0; for(s=s+M-1, t=t+M+1; s^t^1; s>>=1, t>>=1) { if(~s&1) a[s^1] += x; if( t&1) a[t^1] += x; b = max(a[s], a[s^1]), a[s]-=b, a[s^1]-=b, a[s>>1]+=b; b = max(a[t], a[t^1]), a[t]-=b, a[t^1]-=b, a[t>>1]+=b; // printf("%d %d %d %d\n", s, t, a[s^1], a[t^1]); } for( ; s > 1; s>>=1) b = max(a[s], a[s^1]), a[s]-=b, a[s^1]-=b, a[s>>1]+=b; } int Max(int s, int t) { int lans = 0, rans = 0, ans = 0; for(s=s+M-1,t=t+M+1; s^t^1; s>>=1, t>>=1) { lans+=a[s], rans+=a[t]; if(~s&1) lans = max(lans, a[s^1]); if( t&1) rans = max(rans, a[t^1]); // printf("%d %d %d %d\n", s, t, lans, rans); } ans = max(lans+a[s], rans+a[t]); while(s>1) ans+=a[s>>=1]; return ans; } void show() { for(int i = 0; i < M; i++) printf("%d ", a[i]); printf("\n"); } int main() { scanf("%d", &icase); while(icase--) { scanf("%d", &n); clr(a); int num, h1, m1, h2, m2; for(int i = 0; i < n; ++i) { scanf("%d%d:%d%d:%d", &num, &h1, &m1, &h2, &m2); int s1 = h1 * 60 + m1, s2 = h2 * 60 + m2; Add_x(1+s1, s2, num); } // show(); printf("%d\n", Max(1,1440)); } return 0; }