Advertisement
Guest User

Untitled

a guest
May 25th, 2018
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.90 KB | None | 0 0
  1.  
  2. #include "bits/stdc++.h"
  3.  
  4. using namespace std;
  5.  
  6. typedef long long int64;
  7.  
  8. #define x first
  9. #define y second
  10. typedef pair<int,int> pii;
  11. typedef double dbl;
  12. typedef pair<dbl, dbl> pdd;
  13. const dbl eps = 1e-9;
  14.  
  15. struct pt {
  16.   dbl x, y;
  17.   pt () {}
  18.   pt (const dbl &x, const dbl &y): x(x), y(y) {}
  19. };
  20.  
  21. pt operator +(const pt &a, const pt &b) {
  22.   return pt(a.x + b.x, a.y + b.y);
  23. }
  24.  
  25. pt operator -(const pt &a, const pt &b) {
  26.   return pt(a.x - b.x, a.y - b.y);
  27. }
  28.  
  29. dbl operator %(const pt &a, const pt &b) {
  30.   return a.x * b.y - a.y * b.x;
  31. }
  32.  
  33. struct line {
  34.   dbl A, B, C;
  35.   line () {}
  36.   line (const dbl &A, const dbl &B, const dbl &C): A(A), B(B), C(C) {}
  37.   pt intersect(const line &l, bool* success = 0) const {
  38.     // Ax + By = -C
  39.     // A'x + B'y = -C'
  40.     dbl det = A * l.B - B * l.A;
  41.     if (fabs(det) < eps) {
  42.       if (success != 0)
  43.         *success = false;
  44.       return pt();
  45.     }
  46.     if (success != 0) *success = true;
  47.     dbl detx = (-C) * l.B - B * (-l.C);
  48.     dbl dety = A * (-l.C) - (-C) * l.A;
  49.     return pt(detx/det, dety/det);
  50.   }
  51.   dbl getY(const dbl& x) {
  52.     return (-C - A * x) / B;
  53.   }
  54. };
  55.  
  56. int relax(const line& lineA, const line& lineB,
  57.            bool upperA, bool upperB, pdd& infr, bool& active) {
  58.   bool success;
  59.   pt Z = lineA.intersect(lineB, &success);  
  60.   int touch = 0;
  61.   if (!success) {
  62.     touch = -1; // we should have a way to go from one parallel line
  63.                   // to another in cleverIntersect
  64.     // lines are parallel
  65.     // is the borderline of j higher than the one of i?
  66.     bool higher = -lineB.C / lineB.B >
  67.           -lineA.C / lineA.B;
  68.     if (fabs(-lineB.C / lineB.B + lineA.C / lineA.B) < eps)
  69.       return touch;
  70.     if (!(((upperA && upperB) || (!upperA && upperB))
  71.      ^ higher)) {
  72.       active = false;
  73.     }
  74.   } else {
  75.     if ((pt(lineA.A,lineA.B) % pt(lineB.A,lineB.B) < 0)
  76.       ^ upperA) {
  77.       if (infr.y > Z.x - eps) {
  78.     touch = 1;
  79.     infr.y = Z.x;
  80.       }
  81.     } else {
  82.       if (infr.x < Z.x + eps) {
  83.     touch = 2;
  84.     infr.x = Z.x;
  85.       }
  86.     }
  87.   }    
  88.   if (infr.x > infr.y) active = false;
  89.   return touch;
  90. }
  91.  
  92. int IT = 0;
  93.  
  94. void naiveIntersect(const vector<line> &hplanes,
  95.             const vector<bool> &upper,
  96.                           vector<pdd>& influence,
  97.                  // x-segment [l,r] determining the segment
  98.                  // where the corresponding line occurs
  99.                  // in the border of the intersection
  100.               vector<bool>& active) {
  101.   int n = hplanes.size();
  102.   assert(hplanes.size() == upper.size());
  103.   influence.resize(n);
  104.   active.resize(n, true);
  105.   for (int i = 0; i < n; ++i) {
  106.     // i intersect the i'th line with each of the remaining lines
  107.     // and find the segment of influence
  108.     pdd infr = make_pair(-1e9, 1e9);
  109.     for (int j = 0; j < n && active[i]; ++j) {
  110.       ++IT;
  111.       if (i == j) continue;
  112.       bool tactive = true;
  113.       relax(hplanes[i], hplanes[j], upper[i], upper[j],
  114.             infr, tactive);
  115.       active[i] = tactive;
  116.     }    
  117.     influence[i] = infr;  
  118.   }
  119. }
  120.  
  121. void cleverIntersect(const vector<line> &hplanes,
  122.              const vector<bool> &upper,
  123.                           vector<pdd>& influence,
  124.                  // x-segment [l,r] determining the segment
  125.                  // where the corresponding line occurs
  126.                  // in the border of the intersection
  127.               vector<bool>& active,
  128.              int start) {
  129.   int n = hplanes.size();
  130.   assert(hplanes.size() == upper.size());
  131.   influence.resize(n);
  132.   active.resize(n, true);
  133.   vector<bool> used(n, false);
  134.   vector<int> q(n);
  135.   q[0] = start;
  136.   int ql = 0;
  137.   int qr = 1;
  138.   used[start] = true;  
  139.   for (; ql < qr; ++ql) {
  140.     int i = q[ql];
  141.     used[i] = true;
  142.     pdd infr = make_pair(-1e9,1e9);
  143.     int go[2] = {-1,-1};
  144.     for (int j = 0; j < n && active[i]; ++j) {
  145.       ++IT;
  146.       if (i == j) continue;
  147.       bool tactive = true;
  148.       int touch = relax(hplanes[i], hplanes[j], upper[i], upper[j],
  149.             infr, tactive);
  150.       if (touch == -1 && !used[j]) {q[qr++] = j; used[j] = true;}
  151.       if (touch > 0) go[touch-1] = j;
  152.       active[i] = tactive;
  153.     }
  154.     for (int j = 0; j < 2; ++j)
  155.       if (go[j] >= 0 && !used[go[j]]){ q[qr++] = go[j]; used[go[j]] = true;}
  156.     influence[i] = infr;
  157.   }
  158. }
  159.  
  160.  
  161. const int maxn = (int)1.1e5;
  162. const int logn = 17;
  163. int a[maxn];
  164. int64 S[maxn];
  165. int64 dp[maxn];
  166. pair<int, int64> MS[logn][maxn];
  167. int PART = 120;
  168. void solve() {
  169.   int n;
  170.   cin >> n;
  171.   for (int i = 0; i < n; ++i) cin >> a[i];
  172.   S[0] = a[0];
  173.   for (int i = 1; i < n; ++i) S[i] = S[i-1] + int64(a[i]);
  174.  
  175.   // TODO: initialize mergesort log
  176.  
  177.   for (int i = 0; i < n; ++i) dp[i] = S[i] * int64(i+1);
  178.  // for (int i = 0; i < n; ++i) cerr << "dp[" << i << "] = " << dp[i] << endl;  
  179.   for (int i = 0; i * PART < n; ++i) {
  180.     int R = min((i+1) * PART, n);
  181.     int L = i * PART;
  182.    // cerr << L << ".." << R << endl;
  183.     for (int j = L; j < R; ++j) {
  184.       for (int k = L; k < j; ++k) {
  185.         //cout << j << " -> " << k << endl;
  186.         dp[j] = max(dp[j], dp[k] + (S[j] - S[k]) * int64(j - k));
  187.       }
  188.     }
  189.     if (R == n) break;
  190.     vector<line> lines;
  191.     vector<pdd> influence;
  192.     vector<pii> ids;
  193.     vector<bool> used(R-L, false);
  194.     IT = 0;
  195.     for (int j0 = L; j0 < R; ++j0) {
  196.      // cerr << "j0=" << j0 << endl;
  197.       if (used[j0-L]) continue;
  198.       vector<int> q(R-L);
  199.       vector<int> start(R-L);
  200.       q[0] = j0;
  201.       start[0] = -1;
  202.       int ql = 0, qr = 1;
  203.       for (; ql < qr; ++ql) {
  204.     int j = q[ql];
  205.     used[j-L] = true;
  206.     vector<line> loc_lines;
  207.     vector<bool> loc_upper;
  208.     vector<pii> loc_ids;
  209.     int my_start = -1;
  210.     for (int k = L; k < R; ++k)
  211.       if (j != k) {
  212.         if (k == start[ql]) my_start = loc_lines.size();
  213.         loc_lines.push_back(line(S[k]-S[j], k-j, dp[j]-dp[k]
  214.             + int64(j)*S[j] - int64(k)*S[k]));   
  215.         loc_upper.push_back(k > j);
  216.         loc_ids.push_back(make_pair(j,k));
  217.       }
  218.     vector<pdd> loc_influence;
  219.     vector<bool> active;
  220.     if (start[ql] == -1)
  221.       naiveIntersect(loc_lines, loc_upper, loc_influence, active);
  222.     else
  223.       cleverIntersect(loc_lines, loc_upper, loc_influence,
  224.                       active, my_start);
  225.     for (int k = 0; k < (int)loc_lines.size(); ++k)
  226.       if (active[k]) {
  227.        // cout << j << " ==> " << lines.size() << "(" << loc_upper[k] << ")" << endl;
  228.         lines.push_back(loc_lines[k]);
  229.         influence.push_back(loc_influence[k]);
  230.         ids.push_back(loc_ids[k]);
  231.         if (!used[ids.back().y-L]) {
  232.           q[qr] = ids.back().y;
  233.           used[ids.back().y-L] = true;
  234.           start[qr] = j;
  235.           qr++;
  236.         }
  237.     }
  238.       }
  239.     }
  240.   // cerr << IT << endl;
  241.    /* for (int j = 0; j < (int)lines.size(); ++j) {
  242.       cout << "j=" << j << endl;
  243.       cout << ids[j].x << " -- " << ids[j].y << endl;
  244.       cout << lines[j].A << "x + " << lines[j].B << "y + " << lines[j].C << " = " << 0 << endl;
  245.       cout << influence[j].x << ".." << influence[j].y << endl;
  246.     }*/
  247.     vector<int> good_points;
  248.     for (int j = 0; j < (int)influence.size(); ++j) {            
  249.       good_points.push_back((int)influence[j].x);
  250.       good_points.push_back((int)influence[j].x+1);
  251.       good_points.push_back((int)influence[j].y);
  252.       good_points.push_back((int)influence[j].y+1);    
  253.     }
  254.     for (int j = 0; j < (int)good_points.size(); ++j) {
  255.       good_points[j] = max(good_points[j], R-1);
  256.       good_points[j] = min(good_points[j], n-1);
  257.     }
  258.     good_points.push_back(R-1);
  259.     good_points.push_back(n-1);
  260.     sort(good_points.begin(), good_points.end());
  261.     good_points.erase(unique(good_points.begin(), good_points.end()),
  262.                       good_points.end());
  263.    
  264.     for (int j = 1; j < (int)good_points.size(); ++j) {
  265.       int l = good_points[j-1];
  266.       int r = good_points[j];
  267.       vector<int> borders;
  268.      // cout << "l..r=" << l << ".." << r << endl;
  269.       for (int k = 0; k < (int)lines.size(); ++k) {
  270.         if (influence[k].x < (dbl)l + eps &&
  271.        influence[k].y > (dbl)r - eps)
  272.       borders.push_back(k);
  273.       }
  274.      
  275.       for (int k = 0; k < (int)borders.size(); ++k) {
  276.     int u[2] = {ids[borders[k]].x, ids[borders[k]].y};
  277.     for (int p = 0; p < 2; ++p)
  278.       if (u[p] < l) {
  279.         dp[l] = max(dp[l], dp[u[p]] + (S[l]-S[u[p]])*int64(l-u[p]));
  280.       //  cout << "dp[" << l << "] = " << dp[l] << "(" << u[p] << ")" << endl;
  281.       }
  282.       }
  283.      
  284.       vector<pair<int64, int>> sums(r-l+1);
  285.       for (int k = l; k <= r; ++k) sums[k-l] = make_pair(S[k],k);
  286.     //  sort(sums.begin(), sums.end());
  287.      
  288.       if ((int)borders.size() == 0) continue;
  289.       sort(borders.begin(), borders.end(), [&] (int a, int b) {
  290.     if (fabs(lines[a].getY((dbl)(l+r)/2.) -
  291.            lines[b].getY((dbl)(l+r)/2.)) > eps)
  292.       return lines[a].getY((dbl)(l+r)/2.) <
  293.          lines[b].getY((dbl)(l+r)/2.);
  294.     return lines[a].B < lines[b].B;
  295.       });
  296.      // cout << "l="  << l << " r=" << r << endl;      
  297.      // for (int k = 0; k < (int)borders.size(); ++k) cout << borders[k] << ' ';
  298.      // cout << endl;
  299.      
  300.       for (int k = 0; k < (int)sums.size(); ++k) {
  301.     int lb = 0;
  302.     int rb = borders.size() - 1;
  303.     int res = borders.size()-1;
  304.     while (lb <= rb) {
  305.       int mid = (lb+rb)/2;
  306.       if (lines[borders[mid]].getY(sums[k].y) >= sums[k].x) {
  307.         res = mid;
  308.         rb = mid - 1;
  309.       } else {
  310.         lb = mid + 1;
  311.       }
  312.     }
  313.     int ptr = res;
  314.     //cout << sums[k].y << " ptr=" << ptr << endl;
  315.     int cand[4] = {0,0,0,0};
  316.     if (ptr > 0) cand[0] = ids[borders[ptr-1]].x,
  317.                  cand[1] = ids[borders[ptr-1]].y;
  318.     cand[2] = ids[borders[ptr]].x;
  319.     cand[3] = ids[borders[ptr]].y;
  320.     for (int p = 0; p < 4; ++p) {  
  321.       if (sums[k].y <= cand[p]) continue;  
  322.       dp[sums[k].y] = max(dp[sums[k].y], dp[cand[p]] +
  323.         int64(sums[k].y - cand[p]) * (S[sums[k].y] - S[cand[p]])); 
  324.     //  cout << "dp[" << sums[k].y << "] = " << dp[sums[k].y] << "(" << cand[p] << ")" << endl;
  325.     }
  326.       }
  327.     }    
  328.   }
  329.   cerr << (double)clock() / CLOCKS_PER_SEC << endl;
  330.   cout << dp[n-1] << "\n";
  331.  
  332. }
  333.  
  334.  
  335. int main() {
  336.   ios_base::sync_with_stdio(0);
  337.   int t;
  338.   cin >> t;
  339.   for (int i = 0; i < t; ++i) solve();
  340. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement