赞
踩
inline int go(int x, int y){
if(y == 0) return x;
if(x == n) return n + y;
if(y == m) return m + 2 * n - x;
if(x == 0) return (n + m) * 2 - y;
return -1;
}
seg1
,当前线段称为seg2
,如果seg2
的左端点比 seg1
的左端点小那么就是完全包含的情况,不会相交,否则如果seg2
的左端点比seg1
的右端点小就是有交点,我们可以用栈模拟一下即可(可以自己画图理解)。#include <bits/stdc++.h> using namespace std; typedef pair<int,int> PII; vector<PII>q; int n, m, t; inline int go(int x, int y){ if(y == 0) return x; if(x == n) return n + y; if(y == m) return m + 2 * n - x; if(x == 0) return (n + m) * 2 - y; return -1; } int main(){ scanf("%d %d %d",&n, &m, &t); while(t -- ){ int a, b, u, v; scanf("%d %d %d %d",&a, &b, &u, &v); int l = go(a, b), r = go(u, v); if(l > r) swap(l, r); if(l > -1 && r > -1){ q.push_back({r, l}); } } sort(q.begin(), q.end()); stack<PII>stk; for(auto [y, x] : q){ while(!stk.empty() && x < stk.top().first) stk.pop(); if(!stk.empty() && x < stk.top().second){ puts("N"); return 0; } stk.push({x, y}); } puts("Y"); return 0; }
n
次,每次找到第i
次应该写哪门作业,题目要求字典序尽可能最小,那么,我们每次循环,从下标小的往下标大的地方找,每次计算完成作业时间和作业截止时间中间的时间的差值,然后取个前缀最小值,如果能找到某门作业的需要做的时间小于等于前缀最小值且下标的字典序更小就更新一下,遍历n
次即可。#include <bits/stdc++.h> using namespace std; typedef long long LL; int n; int main(){ scanf("%d",&n); vector<array<int,3>>a(n); for(int i = 0; i < n; i ++ ){ int t, d; scanf("%d %d",&t, &d); a[i] = {d, t, i}; } sort(a.begin(), a.end()); LL sum = 0; for(int i = 0; i < n; i ++ ){ if(sum + a[i][1] > a[i][0]){ printf("*\n"); return 0; } sum += a[i][1]; } LL now = 0; while(!a.empty()){//O(n^2) int j = -1, maxn = 1e9 + 1; LL s2 = now; for(int i = 0; i < a.size(); i ++ ){ if(maxn >= a[i][1] && (j == -1 || a[i][2] < a[j][2])){ j = i; } s2 += a[i][1]; maxn = min(maxn * 1ll, a[i][0] - s2); } now += a[j][1]; printf("%d ", a[j][2] + 1); if(a.size() == 1) printf("\n"); a.erase(a.begin() + j); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。