[JSOI2007]建筑抢修
首先我们按自毁时间排序。然后这样从1到n遍历,尝试修复当前第 i 个建筑:如果当前修复建筑所用的时间加上修复第 i 号建筑的时间在自毁前能完成,我们当然要修复它;如果不能完成,那么我们当然要从当前选的ans个建筑以及第i个建筑中修复时间最长的那个把他扔掉,这么做是为了节省时间,好有更大的机会修复后面的建筑。至于如何选取最大值,用优先队列解决。
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #include<cstdlib> 7 #include<stack> 8 #include<queue> 9 #include<vector> 10 #include<cctype> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a) memset(a, 0, sizeof(a)) 15 typedef long long ll; 16 typedef double db; 17 const int INF = 0x3f3f3f3f; 18 const db eps = 1e-8; 19 const int maxn = 1.5e5 + 5; 20 inline ll read() 21 { 22 ll ans = 0; 23 char ch = getchar(), last = ' '; 24 while(!isdigit(ch)) {last = ch; ch = getchar();} 25 while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();} 26 if(last == '-') ans = -ans; 27 return ans; 28 } 29 inline void write(ll x) 30 { 31 if(x < 0) putchar('-'), x = -x; 32 if(x >= 10) write(x / 10); 33 putchar(x % 10 + '0'); 34 } 35 36 int n; 37 struct Node 38 { 39 ll tim, end; 40 bool operator < (const Node& other)const 41 { 42 return end < other.end || (end == other.end && tim < other.tim); 43 } 44 }a[maxn]; 45 46 priority_queue<int> q; 47 ll t; 48 int ans; 49 50 int main() 51 { 52 n = read(); 53 for(int i = 1; i <= n; ++i) a[i].tim = read(), a[i].end = read(); 54 sort(a + 1, a + n + 1); 55 for(int i = 1; i <= n; ++i) 56 { 57 if(t + a[i].tim > a[i].end) //当前建筑来不及修复了 58 { 59 if(!q.empty() && a[i].tim < q.top()) //这个建筑修复的时间不是最长的 60 { 61 t -= q.top(); q.pop(); //不修复那个时间最长的 62 t += a[i].tim; q.push(a[i].tim); 63 } 64 } 65 else 66 { 67 q.push(a[i].tim); 68 ans++; 69 t += a[i].tim; 70 } 71 } 72 write(ans); 73 return 0; 74 }