• Leetcode 1021. Best Sightseeing Pair


    題意

    給定一個數組,求 Aj + Ai - (j - i) 的最大值,其中 j > i,數組長度範圍是 50000。

    題解

    Aj + Ai - (j - i) = (Aj - j) + (Ai + i)

    所以我們可以把原來的數組 a 轉化成兩個數組 aj, ai,其中 ajj = Aj - j, aii = Ai + i,那麼 max{aii + ajj} (i<j) 即爲所求。

    假設 ajj 固定,如果能夠知道 max{aii} (i<j) 的話,那麼對於前 j 個數字,最大值就得到了。於是我們可以提前求出前 i 個數字的 max{ai},記爲數組 pai,複雜度是 O(n)。然後循環 aj 數組,得到 ajj + paij-1 的最大值即爲題目所求,這一步複雜度還是 O(n)。整個複雜度是 O(n)。

     1 class Solution {
     2 public:
     3     int maxScoreSightseeingPair(vector<int>& A) {
     4       VI ai(A.size()), aj(A.size()), pai(A.size());
     5       int res=-1;
     6       REP(i, A.size()) {
     7         ai[i]=A[i]+i;
     8         aj[i]=A[i]-i;
     9         if(i==0) {
    10           pai[i]=ai[i];
    11         } else {
    12           pai[i]=max_(pai[i-1],ai[i]);
    13           res=max_(res,pai[i-1]+aj[i]);
    14         }
    15       }
    16       return res;
    17     }
    18 };
    ︿<(= ̄︶ ̄=)>︿

    在這個基礎上優化代碼:

     1 class Solution {
     2 public:
     3     int maxScoreSightseeingPair(vector<int>& A) {
     4       // A.size() >= 2
     5       VI  pai(A.size());
     6       int res=A[1]+A[0]-1;
     7       pai[0]=A[0];
     8       REP_1(i, A.size()-1) {
     9         pai[i]=max_(pai[i-1],A[i]+i);
    10         res=max_(res,pai[i-1]+A[i]-i);
    11       }
    12       return res;
    13     }
    14 };
    ~o=(`▽`o=)>~=3=3=3

    觀察數組的使用方式,發現後一個元素只依賴於前一個元素,所以還可以再優化:

     1 class Solution {
     2 public:
     3     int maxScoreSightseeingPair(vector<int>& A) {
     4       // A.size() >= 2
     5       int res=A[1]+A[0]-1, tmp=A[0];
     6       REP_1(i, A.size()-1) {
     7         res=max_(res,tmp+A[i]-i);
     8         tmp=max_(tmp,A[i]+i);
     9       }
    10       return res;
    11     }
    12 };
    <(= ̄3 ̄)╭❤

    這樣可讀性其實變差了,但是節省了空間。

    最後貼上完整的代碼:

      1 // ==================================================
      2 
      3 // C library
      4 #include <cassert>
      5 #include <cmath>
      6 #include <climits>
      7 #include <cstdio>
      8 #include <cstdlib>
      9 #include <cstring>
     10 #include <cctype>
     11 #include <ctime>
     12 
     13 // Containers
     14 #include <vector>
     15 #include <list>
     16 #include <stack>
     17 #include <queue>
     18 #include <deque>
     19 #include <set>
     20 #include <map>
     21 #include <unordered_set>
     22 #include <unordered_map>
     23 
     24 // Input/Output
     25 #include <iostream>
     26 #include <istream>
     27 #include <ostream>
     28 #include <sstream>
     29 #include <fstream>
     30 #include <ios>
     31 #include <iomanip>
     32 
     33 // Other
     34 #include <tuple>
     35 #include <string>
     36 #include <tuple>
     37 #include <bitset>
     38 #include <algorithm>
     39 #include <utility>
     40 #include <type_traits>
     41 #include <iterator>
     42 #include <limits>
     43 #include <stdexcept>
     44 #include <random>
     45 #include <chrono>
     46 
     47 // ==================================================
     48 
     49 using namespace std;
     50 
     51 // constants
     52 const double EPS = 1e-9;
     53 
     54 // type alias
     55 using PII = pair<int, int>;
     56 using LL = long long int;
     57 using VI = vector<int>;
     58 using VC = vector<char>;
     59 using VS = vector<string>;
     60 using VVI = vector<VI>;
     61 using MII = map<int, int>;
     62 using MCI = map<char, int>;
     63 using SI = set<int>;
     64 
     65 // ==================================================
     66 
     67 // fast IO
     68 static auto __2333__ = []() {
     69                          ios::sync_with_stdio(false); cin.tie(nullptr); return 0; }();
     70 
     71 // ==================================================
     72 
     73 // some macro for less typing
     74 #define max_(x, y) ((x) > (y) ? (x) : (y))
     75 #define min_(x, y) ((x) > (y) ? (y) : (x))
     76 
     77 #define REP(i, n) for (int i = 0; i < int(n); ++i) // [0, n)
     78 #define REPV(i, n) for (int i = int(n - 1); i >= 0; --i)   // reverse [0, n)
     79 #define FOR(i, a, b) for (int i = int(a); i < int(b); ++i) // [a, b)
     80 #define DWN(i, b, a) for (int i = int(b - 1); i >= int(a); --i) // reverse [a, b)
     81 
     82 #define REP_1(i, n) for (int i = 1; i <= int(n); ++i)           // [1, n]
     83 #define REPV_1(i, n) for (int i = int(n); i >= 1; --i)          // reverse [1, n]
     84 #define FOR_1(i, a, b) for (int i = int(a); i <= int(b); ++i)   // [a, b]
     85 #define DWN_1(i, b, a) for (int i = int(b); i >= a; --i)        // reverse [a, b]
     86 
     87 // DEBUG PRINT macro
     88 #define PR(x) cout << #x " = " << (x) << "	"
     89 #define NL cout << "
    "
     90 
     91 #define PR1(x) PR(x), NL
     92 #define PR2(x1, x2) PR(x1), PR1(x2)
     93 #define PR3(x1, x2, x3) PR(x1), PR2(x2, x3)
     94 #define PR4(x1, x2, x3, x4) PR(x1), PR3(x2, x3, x4)
     95 
     96 int direction[8][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1},
     97                                                     {-1, -1}, {-1, 1}, {1, -1}, {1, 1} };
     98 
     99 // ==================================================
    100 
    101 // simplest print
    102 template<typename T>
    103 void PRC(const T& a) { cout << a << " "; }
    104 
    105 // print container
    106 template<typename T>
    107 void PRCO(const T& c) { for (auto x : c) PRC(x); NL; }
    108 
    109 // print vector
    110 template<typename T>
    111 void PRV(const vector<T>& c) { PRCO<vector<T>>(c); }
    112 
    113 // print C-style array
    114 template<typename T, size_t N>
    115 void PRA(const T (&ar)[N]) {
    116   for (auto x : ar) PRC(x); NL;
    117 }
    118 
    119 // print pair
    120 template<typename T1, typename T2>
    121 void PRP(const pair<T1, T2>& p) { PRC(p.first); PRLN(p.second); }
    122 
    123 // print a value and a new line
    124 template<typename T>
    125 void PRLN(const T& a) { cout << a << "
    "; }
    126 
    127 // ==================================================
    128 // math
    129 bool is_prime(LL x)
    130 {
    131   if (x == 1) return false;
    132   assert(x > 1);
    133   LL m = ceil(sqrt(x));
    134   FOR_1(i, 2, m) { if (!(x % i)) return false; }
    135   return true;
    136 }
    137 
    138 // prime table
    139 const int PRIME_MAX = 10;
    140 VI prime_table;
    141 vector<bool> prime_table_bool(PRIME_MAX, true);
    142 
    143 void get_prime() {
    144   FOR_1(i, 2, PRIME_MAX) {
    145     if (prime_table_bool[i]) {
    146       prime_table.push_back(i);
    147       for (int j = i << 1; j <= PRIME_MAX; j += i) prime_table_bool[j] = false;
    148     }
    149   }
    150 }
    151 
    152 // double equals
    153 bool eq(double a, double b) { return fabs(a - b) < EPS; }
    154 
    155 double random_() {
    156   // generate random number in [0, 1]
    157   return double(rand()) / RAND_MAX;
    158 }
    159 
    160 int random_(int m) {
    161   // generate random int between [0, m - 1]
    162   return int(random_() * (m - 1) + 0.5);
    163 }
    164 
    165 // high precision integer
    166 
    167 class BNI {
    168   friend ostream &operator<<(ostream &, const BNI &);
    169   friend istream &operator>>(istream &, BNI &);
    170 public:
    171   BNI() = default;
    172   BNI(const string &s) { *this = s; }
    173   BNI(const char s[]) :BNI(string(s)) {}
    174   BNI(const BNI &rhs) = default;
    175   BNI(const LL n) { *this = n; };
    176   BNI(istream &in) { string s; in >> s; *this = s; }
    177 
    178   BNI &operator=(const BNI &rhs) = default;
    179   BNI &operator=(const string &s) {
    180     string s_ = clean_zero_str(s);
    181     num.resize(s_.size());
    182     int i = 0;
    183     for (auto it = s_.crbegin(); it != s_.crend(); ++it)
    184       num[i++] = *it - '0';
    185     return *this;
    186   }
    187   BNI &operator=(const char s[]) {
    188     operator=(string(s));
    189     return *this;
    190   }
    191   BNI &operator=(LL n) {
    192     stringstream ss; ss << n;
    193     string s; ss >> s;
    194     *this = s;
    195     return *this;
    196   }
    197   BNI operator+(const BNI &rhs) const {
    198     BNI res;
    199     size_t max_len = max_(num.size(), rhs.num.size());
    200     int x;
    201     for (int i = 0, rem = 0; rem || i < max_len; ++i) {
    202       x = rem;
    203       if (i < num.size()) x += num[i];
    204       if (i < rhs.num.size()) x += rhs.num[i];
    205       res.num.push_back(x % 10);
    206       rem = x / 10;
    207     }
    208     res.clean_zero();
    209     return res;
    210   }
    211   BNI& operator+=(const BNI &rhs) {
    212     *this = *this + rhs;
    213     return *this;
    214   }
    215   BNI operator*(const BNI &rhs) const {
    216     BNI res;
    217     size_t sum_len = num.size() + rhs.num.size();
    218     res.num.resize(sum_len);
    219     for (size_t i = 0; i < num.size(); ++i) {
    220       for (size_t j = 0; j < rhs.num.size(); ++j) {
    221         res.num[i + j] += num[i] * rhs.num[j];
    222       }
    223     }
    224     for (size_t i = 0; i < res.num.size() - 1; ++i) {
    225       res.num[i + 1] += res.num[i] / 10;
    226       res.num[i] %= 10;
    227     }
    228     res.clean_zero();
    229     return res;
    230   }
    231   BNI& operator*=(const BNI &rhs) {
    232     *this = *this * rhs;
    233     return *this;
    234   }
    235   /*
    236    * assume *this >= rhs
    237    */
    238   BNI operator-(const BNI &rhs) const {
    239     assert(*this >= rhs);
    240     if (rhs == 0LL) return *this;
    241     BNI res;
    242     int x;
    243     for (int i = 0, rem = 0; i < num.size(); ++i) {
    244       x = num[i] - rem;
    245       if (i < rhs.num.size()) x -= rhs.num[i];
    246       if (x >= 0) rem = 0;
    247       else { rem = 1; x += 10; }
    248       res.num.push_back(x);
    249     }
    250     res.clean_zero();
    251     return res;
    252   }
    253   BNI& operator-=(const BNI &rhs) {
    254     *this = *this - rhs;
    255     return *this;
    256   }
    257   /*
    258    * assume rhs is not zero
    259    */
    260   pair<BNI, BNI> operator/(const BNI &rhs) const {
    261     assert(BNI(0LL) != rhs);
    262     if (*this < rhs) return make_pair(0LL, *this);
    263 
    264     BNI quotient, rem;
    265     string nume = c_str();
    266     string numerator = nume.substr(0, rhs.num.size());
    267     size_t pos = rhs.num.size();
    268     vector<BNI> times(10);
    269     for (int i = 0; i < 10; ++i) times[i] = rhs * i;
    270     string quot;
    271 
    272     while (pos <= nume.size()) {
    273       BNI nume_b = numerator;
    274       int cnt = 0;
    275 
    276       while (cnt < 10 && times[cnt] <= nume_b) ++cnt;
    277       --cnt;
    278 
    279       quot += char(cnt + '0');
    280       rem = nume_b - times[cnt];
    281 
    282       if (pos < nume.size())
    283         numerator = rem.c_str() + nume[pos];
    284 
    285       ++pos;
    286     }
    287 
    288     quotient = quot;
    289 
    290     return make_pair(quotient, rem);
    291   }
    292   bool operator<(const BNI &rhs) const {
    293     if (num.size() == 0) return !(rhs.num.size() == 0);
    294     if (num.size() != rhs.num.size()) {
    295       return num.size() < rhs.num.size();
    296     }
    297     for (int i = num.size() - 1; i >= 0; --i) {
    298       if (num[i] != rhs.num[i]) return num[i] < rhs.num[i];
    299     }
    300     return false;
    301   }
    302   bool operator>(const BNI &rhs) const { return rhs < *this; }
    303   bool operator<=(const BNI &rhs) const { return !(*this > rhs); }
    304   bool operator>=(const BNI &rhs) const { return !(*this < rhs); }
    305   bool operator!=(const BNI &rhs) const { return (*this < rhs) || (*this > rhs); }
    306   bool operator==(const BNI &rhs) const { return !(*this != rhs); }
    307   size_t size() const { return num.size(); }
    308   string c_str() const {
    309     string s;
    310     for (auto x : num) s = char(x + '0') + s;
    311     return s.empty() ? "0" : s;
    312   }
    313   void left_shift() {
    314     if (!num.empty()) num.pop_back();
    315   }
    316 protected:
    317   vector<int> num;
    318   string clean_zero_str(const string &s) {
    319     if (s.empty() || s[0] != '0') return s;
    320     size_t i = 0;
    321     while (i < s.size() && '0' == s[i]) ++i;
    322     return s.substr(i);
    323   }
    324   void clean_zero() {
    325     for (auto it = num.rbegin(); it != num.rend() && *it == 0;) {
    326       ++it;
    327       num.pop_back();
    328     }
    329   }
    330 };
    331 
    332 ostream &operator<<(ostream &out, const BNI &x) {
    333   out << x.c_str();
    334   return out;
    335 }
    336 
    337 istream &operator>>(istream &in, BNI &x) {
    338   x = BNI(in);
    339   return in;
    340 }
    341 
    342 // high precision float
    343 class BNF : protected BNI {
    344   friend ostream &operator<<(ostream &out, const BNF &x);
    345   friend istream &operator>>(istream &in, BNF &x);
    346 public:
    347   BNF() = default;
    348   BNF(const string &s) { *this = s; }
    349   BNF(const char s[]): BNF(string(s)) {}
    350   BNF(const BNF &rhs) = default;
    351   BNF(const LL n) { *this = n; }
    352   BNF(istream &in) { string s; in >> s; *this = s; }
    353 
    354   BNF &operator=(const string &s) {
    355     string s_ = clean_zero_str(s);
    356     num.resize(s_.size());
    357     int i = 0;
    358     for (auto it = s_.crbegin(); it != s_.crend(); ++it)
    359       num[i++] = *it - '0';
    360     return *this;
    361   }
    362   BNF &operator=(const char s[]) {
    363     operator=(string(s)); return *this;
    364   }
    365   BNF &operator=(LL n) {
    366     stringstream ss; ss << n;
    367     string s; ss >> s;
    368     *this = s;
    369     return *this;
    370   }
    371   BNF operator+(const BNF &rhs) const {
    372     pair<string, string> in_fr1 = split(), in_fr2 = rhs.split();
    373     string inte1 = in_fr1.first, frac1 = in_fr1.second,
    374       inte2 = in_fr2.first, frac2 = in_fr2.second;
    375     LL inc = 0LL;
    376     BNI frac_sum;
    377     inc += sum_has_carry(frac1, frac2, frac_sum);
    378     BNI inte_sum = BNI(inte1) + inte2 + inc;
    379 
    380     return join_inte_frac(inte_sum, frac_sum);
    381   }
    382   BNF& operator+=(const BNF &rhs) {
    383     *this = *this + rhs;
    384     return *this;
    385   }
    386   /*
    387    * assume *this >= rhs
    388    */
    389   BNF operator-(const BNF &rhs) const {
    390     assert(*this >= rhs);
    391     pair<string, string> in_fr1 = split(), in_fr2 = rhs.split();
    392     string inte1 = in_fr1.first, frac1 = in_fr1.second,
    393       inte2 = in_fr2.first, frac2 = in_fr2.second;
    394     LL dec = 0LL;
    395     if (BNI(frac1) < frac2) {
    396       frac1 = '1' + frac1; ++dec;
    397     }
    398     while (frac1.size() < frac2.size()) frac1 += '0';
    399     while (frac2.size() < frac1.size()) frac2 += '0';
    400     BNI frac = BNI(frac1) - frac2;
    401     BNI inte = BNI(inte1) - dec - inte2;
    402     return join_inte_frac(inte, frac);
    403   }
    404   BNF& operator-=(const BNF &rhs) {
    405     return *this = *this - rhs;
    406   }
    407   BNF operator*(const BNF &rhs) const {
    408     pair<string, string> in_fr1 = split(), in_fr2 = rhs.split();
    409     string inte1 = in_fr1.first, frac1 = in_fr1.second,
    410       inte2 = in_fr2.first, frac2 = in_fr2.second;
    411     BNI res = BNI(inte1 + frac1) * (inte2 + frac2);
    412     int deci = decimals + rhs.decimals;
    413     string res_s = res.c_str();
    414     while (res_s.size() < deci) res_s = '0' + res_s;
    415     return BNF(res_s.substr(0, res_s.size() - deci) + '.'
    416                + res_s.substr(res_s.size() - deci));
    417   }
    418   BNF& operator*=(const BNF &rhs) {
    419     return *this = *this * rhs;
    420   }
    421   bool operator<(const BNF &rhs) const {
    422     pair<string, string> in_fr1 = split(), in_fr2 = rhs.split();
    423     string inte1 = in_fr1.first, frac1 = in_fr1.second,
    424       inte2 = in_fr2.first, frac2 = in_fr2.second;
    425     if (inte1 < inte2) return true;
    426     else if (inte1 == inte2) return frac1 < frac2;
    427     else return false;
    428   }
    429   bool operator>(const BNF &rhs) const { return rhs < *this; }
    430   bool operator<=(const BNF &rhs) const { return !(*this > rhs); }
    431   bool operator>=(const BNF &rhs) const { return !(*this < rhs); }
    432   bool operator!=(const BNF &rhs) const { return (*this < rhs) || (*this > rhs); }
    433   bool operator==(const BNF &rhs) const { return !(*this != rhs); }
    434 
    435 protected:
    436   int decimals = 0;
    437   LL sum_has_carry(const BNI &a, const BNI &b, BNI &sum) const {
    438     int max_len = max_(a.size(), b.size());
    439     sum = a + b;
    440     if (sum.size() > max_len) { sum.left_shift(); return 1LL; }
    441     return 0LL;
    442   }
    443   BNF join_inte_frac(const BNI &inte, const BNI &frac) const {
    444     return BNF(inte.c_str() + "." + frac.c_str());
    445   }
    446   string clean_tail_zero_str(const string &s) {
    447     int i = 0;
    448     string r;
    449     while (i < s.size() && '.' != s[i]) r += s[i++];
    450 
    451     int j = s.size() - 1;
    452     while (j >= 0 && '0' == s[j]) --j;
    453     for (int k = i + 1; k <= j; ++k) r += s[k];
    454     decimals = j >= i ? j - i : 0;
    455     return r;
    456   }
    457   string clean_zero_str(const string &s) {
    458     string r = BNI::clean_zero_str(s);
    459     return clean_tail_zero_str(r);
    460   }
    461   string c_str() const {
    462     string s;
    463     for (int i = 0; i < num.size(); ++i) {
    464       if (i == decimals) s = '.' + s;
    465       s = char(num[i] + '0') + s;
    466     }
    467     if (s.empty()) s = "0";
    468     if (num.size() == decimals) s = '.' + s;
    469     return s;
    470   }
    471   pair<string, string> split() const {
    472     string s = c_str();
    473     size_t p = s.find('.');
    474     return make_pair(s.substr(0, p), s.substr(p + 1));
    475   }
    476 };
    477 
    478 ostream &operator<<(ostream &out, const BNF &x) {
    479   cout << x.c_str(); return out;
    480 }
    481 
    482 istream &operator>>(istream &in, BNF &x) {
    483   x = BNF(in); return in;
    484 }
    485 
    486 // Trie Tree
    487 const int ALPHASIZE = 26;
    488 
    489 class TrieNode {
    490 public:
    491   TrieNode()
    492     :wordEnd{false}, cnt{1}
    493   {
    494     REP(i, ALPHASIZE) { child[i] = nullptr; }
    495   }
    496   ~TrieNode() {}
    497   void insert(string word) {
    498     int i;
    499     TrieNode *cur = this;
    500     for (auto x:word) {
    501       i = x - 'a';
    502       if (nullptr == cur->child[i]) {
    503         cur->child[i] = new TrieNode();
    504         cur = cur->child[i];
    505       } else {
    506         cur = cur->child[i];
    507         ++cur->cnt;
    508       }
    509     }
    510     cur->wordEnd = true;
    511   }
    512   bool search(string word) {
    513     int i;
    514     TrieNode *cur = this;
    515     for (auto x:word) {
    516       i = x - 'a';
    517       if (nullptr == cur->child[i]) {
    518         return false;
    519       }
    520       cur = cur->child[i];
    521     }
    522     return cur->wordEnd;
    523   }
    524   int cnt_words(string word) {
    525     int i; TrieNode *cur = this;
    526     for(auto x:word) {
    527       i = x - 'a';
    528       if (nullptr == cur->child[i]) return 0;
    529       cur = cur->child[i];
    530     }
    531     return cur->cnt;
    532   }
    533   TrieNode *child[ALPHASIZE];
    534   bool wordEnd;
    535   int cnt; // number of words with the prefix
    536 };
    537 
    538 
    539 
    540 // ==================================================
    541 
    542 
    543 // accepted version 3
    544 
    545 class Solution {
    546 public:
    547     int maxScoreSightseeingPair(vector<int>& A) {
    548       // A.size() >= 2
    549       int res=A[1]+A[0]-1, tmp=A[0];
    550       REP_1(i, A.size()-1) {
    551         res=max_(res,tmp+A[i]-i);
    552         tmp=max_(tmp,A[i]+i);
    553       }
    554       return res;
    555     }
    556 };
    557 
    558 int main( void ) {
    559 
    560 #ifdef DEBUG
    561   freopen("c.in", "r", stdin);
    562 #endif
    563 
    564   Solution sol;
    565   int x; VI a;
    566   while (cin>>x) {
    567     a.push_back(x);
    568   }
    569   PRCO(a);
    570   PRLN(sol.maxScoreSightseeingPair(a));
    571 
    572   return 0;
    573 }
    ヾ<(≧奋≦)>〃

    end.

  • 相关阅读:
    腾讯云 Centos 配置 JDK & Tomcat & Mysql
    JNI编程新手入门:Java和C++的超简单交互
    关于正则表达式的一些实际应用
    CAJ 转化为PDF
    Latex 大括号后多行输出
    Latex 安装
    Neo4j使用操作
    pip 升级操作
    venue recommendation —— 应用场景/用户分类
    Recbole安装及使用
  • 原文地址:https://www.cnblogs.com/algouage/p/10598424.html
Copyright © 2020-2023  润新知