1. 程式人生 > >牛客網暑期ACM多校訓練營(第二場)菜鳥補題QAQ

牛客網暑期ACM多校訓練營(第二場)菜鳥補題QAQ

warn 分享圖片 ini lin int 技術分享 ace main bre

  G transform

  題目大意: 數軸上有n個集裝箱,第i個集裝箱位於坐標x[i],有a[i]件貨物。現在要把集裝箱進行一些移動,求在所有貨物移動總距離不超過T的情況下,最多能把多少個集裝箱移動到同一個位置

  解法: https://www.nowcoder.com/discuss/88268?type=101&order=0&pos=1&page=1

技術分享圖片
  1 #include <iostream>
  2 #include <string.h>
  3 #include <cstdio>
  4 #include <vector>
  5
#include <queue> 6 #include <stack> 7 #include <math.h> 8 #include <string> 9 #include <algorithm> 10 #include <functional> 11 12 #define SIGMA_SIZE 26 13 #define lson rt<<1 14 #define rson rt<<1|1 15 #define lowbit(x) (x&-x) 16 #define
foe(i, a, b) for(int i=a; i<=b; i++) 17 #define fo(i, a, b) for(int i=a; i<b; i++) 18 #define pii pair<int,int> 19 #pragma warning ( disable : 4996 ) 20 21 using namespace std; 22 typedef long long LL; 23 inline double dMax(double a, double b) { return a>b ? a : b; } 24 inline double
dMin(double a, double b) { return a>b ? b : a; } 25 inline LL LMax(LL a, LL b) { return a>b ? a : b; } 26 inline LL LMin(LL a, LL b) { return a>b ? b : a; } 27 inline LL lgcd(LL a, LL b) { return b == 0 ? a : lgcd(b, a%b); } 28 inline LL llcm(LL a, LL b) { return a / lgcd(a, b)*b; } //a*b = gcd*lcm 29 inline int Max(int a, int b) { return a>b ? a : b; } 30 inline int Min(int a, int b) { return a>b ? b : a; } 31 inline int gcd(int a, int b) { return b == 0 ? a : gcd(b, a%b); } 32 inline int lcm(int a, int b) { return a / gcd(a, b)*b; } //a*b = gcd*lcm 33 const LL INF = 0x3f3f3f3f3f3f3f3f; 34 const LL mod = 1e9+7; 35 const double eps = 1e-8; 36 const int inf = 0x3f3f3f3f; 37 const int maxk = 3e6 + 5; 38 const int maxn = 5e5+5; 39 40 LL n, mmax; 41 LL T; 42 LL pos[maxn], val[maxn]; 43 LL sum[maxn], dsum[maxn]; 44 45 //將區間的所有貨物移動到最左端點需要的花費 46 LL leftCal(int lhs, int rhs) 47 { 48 LL tmp = dsum[rhs]-dsum[lhs-1] - (sum[rhs]-sum[lhs-1])*pos[lhs]; 49 return tmp; 50 } 51 52 //將區間的所有貨物移動到最右端點 53 LL rightCal(int lhs, int rhs) 54 { 55 LL tmp = (pos[rhs]-pos[lhs])*(sum[rhs]-sum[lhs-1]) - leftCal(lhs, rhs); 56 return tmp; 57 } 58 59 void init() 60 { 61 scanf("%lld %lld", &n, &T); T >>= 1; 62 mmax = sum[0] = dsum[0] = 0; 63 foe(i, 1, n) 64 scanf("%lld", &pos[i]); 65 foe(i, 1, n) 66 { 67 scanf("%lld", &val[i]); 68 mmax = LMax(mmax, val[i]); 69 sum[i] = sum[i-1] + val[i]; 70 dsum[i] = dsum[i-1]+pos[i]*val[i]; 71 } 72 } 73 74 bool judge(LL num) 75 { 76 //貨物數量的中位數 77 LL mid = num/2+1; 78 79 LL l = 1, r = 1, i = 1; 80 LL more = 0; 81 while (1) { 82 while ( r <= n && sum[r]-sum[l-1] < num ) r++; 83 while ( i <= n && sum[i]-sum[l-1] < mid ) i++; 84 if ( r > n || i > r ) 85 break; 86 87 more = sum[r]-sum[l-1]-num; 88 if ( (rightCal(l, i)+leftCal(i, r)-more*(pos[r]-pos[i])) <= T ) 89 return true; 90 l++; 91 } 92 93 l = r = i = n; more = 0; 94 while (1) { 95 while ( l >= 1 && sum[r]-sum[l-1] < num ) l--; 96 while ( i >= 1 && sum[r]-sum[i-1] < mid ) i--; 97 if ( l < 1 || i < l ) 98 break; 99 100 more = sum[r]-sum[l-1]-num; 101 if ( (rightCal(l,i)+leftCal(i,r)-more*(pos[i]-pos[l])) <= T ) 102 return true; 103 r--; 104 } 105 106 return false; 107 } 108 109 int main() 110 { 111 init(); 112 113 LL lhs = mmax, rhs = sum[n]; 114 LL mid; 115 while (lhs <= rhs) 116 { 117 mid = (lhs+rhs)>>1; 118 if (judge(mid)) 119 lhs = mid+1; 120 else 121 rhs = mid-1; 122 } 123 124 printf("%lld\n", rhs); 125 return 0; 126 }
View Code

牛客網暑期ACM多校訓練營(第二場)菜鳥補題QAQ