题目链接:https://vjudge.net/problem/UVALive-7261
题意略
三个步骤:
1.二分满足左边绿洲面积大于等于右边绿洲面积,并且使左边面积尽可能大的分割线位置。
2.判断这个分割线是否包含于任何一个绿洲中,如果包含,那么直接输出结果就行,否则:
3.从此坐标向右扫描,找到下一个绿洲的左边界,此为答案。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 typedef struct Sq { LL x, y, w, h; }Sq; 6 const int maxn = 10100; 7 LL n, k; 8 Sq sq[maxn]; 9 LL sum; 10 map<LL, int> vis; 11 12 bool ok1(LL val) { 13 LL a = 0; 14 for(int i = 0; i < k; i++) { 15 if(sq[i].x + sq[i].w <= val) a += sq[i].w * sq[i].h; 16 else if(sq[i].x <= val && val <= sq[i].x+sq[i].w) { 17 a += sq[i].h * (val - sq[i].x); 18 } 19 } 20 LL b = sum - a; 21 return a >= b; 22 } 23 24 int main() { 25 // freopen("in", "r", stdin); 26 int T; 27 LL x, y, w, h; 28 scanf("%d", &T); 29 while(T--) { 30 scanf("%lld%lld",&n,&k); 31 sum = 0; vis.clear(); 32 vis[n] = 1; 33 for(int i = 0; i < k; i++) { 34 scanf("%lld%lld%lld%lld",&x,&y,&w,&h); 35 sq[i] = Sq{x,y,w,h}; 36 vis[x] = 1; 37 sum += w * h; 38 } 39 LL lo = 0, hi = n; 40 LL ret = 0; 41 while(lo <= hi) { 42 LL mid = (lo + hi) >> 1; 43 if(ok1(mid)) { 44 ret = mid; 45 hi = mid - 1; 46 } 47 else lo = mid + 1; 48 } 49 bool flag = 0; 50 for(int i = 0; i < k; i++) { 51 if(sq[i].x <= ret && ret < sq[i].x+sq[i].w) { 52 flag = 1; 53 break; 54 } 55 } 56 if(flag) { 57 printf("%lld\n", ret); 58 continue; 59 } 60 LL remain = 0; 61 for(LL i = ret; i <= n; i++) { 62 if(vis.find(i) != vis.end()) { 63 remain = i - ret; 64 break; 65 } 66 } 67 printf("%lld\n", ret+remain); 68 } 69 return 0; 70 }
[UVALive7261]A - Xiongnu's Land (二分)
时间: 2024-12-13 01:15:11