牛客网暑期ACM多校训练营(第二场)菜鸟补题QAQ

  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

猜你喜欢

转载自www.cnblogs.com/chaoswr/p/9416995.html
今日推荐