思路:
时间复杂度:\(O(n)\)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 void solve () { int n; std::cin >> n; std::vector<int > a (n) ; for (int i = 0 ; i < n; i++) { std::cin >> a[i]; } int p = 0 , A = 0 , B = 0 ; for (int i = n - 1 ; i >= 0 ; i--, p++) { if (p % 2 == 0 ) { A += a[i]; } else { B += a[i]; } } std::cout << (A > B ? "Alice\n" : "Bob\n" ); }
思路:
时间复杂度:\(O(nlogn)\)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 void solve () { int n; std::cin >> n; std::vector<int > a (n) ; for (int i = 0 ; i < n; i++) { std::cin >> a[i]; } std::vector<int > b = a; std::sort (b.begin (), b.end ()); if (b[0 ] == a[0 ] || b[n - 1 ] == a[n - 1 ]) { std::cout << "YES\n" ; } else { std::cout << "NO\n" ; } }
思路:
首先定位光标,然后模拟这个两种操作
注意erase
的时间复杂度是logn
的,n
的范围是2e5
,时间复杂度nlogn
可以过本题
时间复杂度:\(O(nlogn)\)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 signed main () { std::ios::sync_with_stdio (false ); std::cin.tie (nullptr ); int n, k; std::cin >> n >> k; std::string s; std::cin >> s; s = '&' + s + '&' ; n = s.size (); int p = 0 ; for (int i = 0 ; i < n; i++) { if (s[i] == 'I' ) { p = i; break ; } } for (int i = 0 ; i < k; i++) { std::string op; std::cin >> op; if (op == "backspace" ) { char a = s[p - 1 ]; char b = s[p + 1 ]; if (a == '&' ) continue ; if (a == '(' && b == ')' ) { s.erase (s.begin () + p + 1 ); s.erase (s.begin () + p - 1 ); p--; } else { s.erase (s.begin () + p - 1 ); p--; } } else { char a = s[p - 1 ]; char b = s[p + 1 ]; if (b == '&' ) continue ; s.erase (s.begin () + p + 1 ); } } for (char c : s) { if (c == '&' ) continue ; std::cout << c; } std::cout << "\n" ; return 0 ; }
思路:
和简单版本的思路基本完全一样,只不过加了个光标移动的属性
模拟即可
时间复杂度:\(O(nlogn)\)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 signed main () { std::ios::sync_with_stdio (false ); std::cin.tie (nullptr ); int n, k; std::cin >> n >> k; std::string s; std::cin >> s; s = '&' + s + '&' ; n = s.size (); int p = 0 ; for (int i = 0 ; i < n; i++) { if (s[i] == 'I' ) { p = i; break ; } } for (int i = 0 ; i < k; i++) { std::string op; std::cin >> op; if (op == "backspace" ) { char a = s[p - 1 ]; char b = s[p + 1 ]; if (a == '&' ) continue ; if (a == '(' && b == ')' ) { s.erase (s.begin () + p + 1 ); s.erase (s.begin () + p - 1 ); p--; } else { s.erase (s.begin () + p - 1 ); p--; } } else if (op == "delete" ) { char a = s[p - 1 ]; char b = s[p + 1 ]; if (b == '&' ) continue ; s.erase (s.begin () + p + 1 ); } else if (op == "<-" ) { if (s[p - 1 ] == '&' ) continue ; std::swap (s[p - 1 ], s[p]); p--; } else if (op == "->" ) { if (s[p + 1 ] == '&' ) continue ; std::swap (s[p + 1 ], s[p]); p++; } } for (int i = 0 ; i < s.size (); i++) { if (s[i] == '&' ) continue ; std::cout << s[i]; } std::cout << "\n" ; return 0 ; }
思路:
我们可以试一下几种情况,可以发现只要我们每次向一个方向正 or 负
,那么最终的极值差一定不会改变
然后我们大胆猜测,这个与取值正负无关
所以我们只需要,找逆序即可,然后按规则模拟
时间复杂度:\(O(n)\)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 signed main () { std::ios::sync_with_stdio (false ); std::cin.tie (nullptr ); int n; std::cin >> n; std::vector<int > a (n + 1 ) ; for (int i = 0 ; i < n; i++) { std::cin >> a[i]; } int max = *max_element (a.begin (), a.end ()); a[n] = max; std::vector<int > ans (n) ; for (int i = 1 ; i <= n; i++) { if (a[i] < a[i - 1 ]) { ans[i] = a[i - 1 ] - a[i]; a[i] += ans[i]; } } for (int i = 0 ; i < n; i++) { std::cout << ans[i] << " \n" [i == n - 1 ]; } return 0 ; }
思路:
首先我们考虑枚举l
和r
两个端点,首先O(n)
的枚举任意一个端点,会发现两个端点都到O(n^2)
了,所以其中一个定要优化到logn
才可以
然后我们可以发现一个性质,在做&
运算时,最多只会有logn
个取值,然后我们先预处理&
运算的过程,用cnt[i][j]
来维护前i
位中1
的个数
我们将那些出现进行&
运算,出现递减序的位置进行存储,然后开始O(n)
的枚举l
端点
时间复杂度:\(O(nlogn)\)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 signed main () { std::ios::sync_with_stdio (false ); std::cin.tie (nullptr ); int n; std::cin >> n; std::vector<int > a (n + 1 ) ; std::vector cnt (n + 1 , std::vector<int >(30 )) ; for (int i = 1 ; i <= n; i++) { std::cin >> a[i]; for (int j = 0 ; j < 30 ; j++) { cnt[i][j] = cnt[i - 1 ][j]; if ((a[i] >> j) & 1 ) cnt[i][j]++; } } std::vector<int > f (n + 2 ) ; f[n + 1 ] = (1LL << 31 ) - 1 ; std::vector<int > p; for (int i = n; i >= 1 ; i--) { f[i] = f[i + 1 ] & a[i]; if (f[i] < f[i + 1 ]) { p.emplace_back (i); } } i64 ans = 0 , val = 0 ; for (int i = 1 ; i <= n; i++) { val ^= a[i]; for (int j = 0 ; j < p.size (); j++) { if (i + 1 < p[j]) { int l = i + 1 , r = p[j] - 1 ; int t = 0 ; for (int k = 0 ; k < 30 ; k++) { if (cnt[r][k] - cnt[l - 1 ][k] > 0 ) { t |= 1 << k; } } ans = std::max (ans, val + t + f[r + 1 ]); } } } std::cout << ans << "\n" ; return 0 ; }
思路:
前置知识:树状数组求逆序对
首先我们将每一个值得下标存储,
时间复杂度:\(O(n \times (logn +
\sqrt{n}))\)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 template <typename T>struct Fenwick { int n; std::vector<T> a; Fenwick (int n_ = 0 ) { init (n_); } void init (int n_) { n = n_; a.assign (n, T{}); } void add (int x, const T &v) { for (int i = x + 1 ; i <= n; i += i & -i) { a[i - 1 ] = a[i - 1 ] + v; } } T sum (int x) { T ans{}; for (int i = x; i > 0 ; i -= i & -i) { ans = ans + a[i - 1 ]; } return ans; } T rangeSum (int l, int r) { return sum (r) - sum (l); } }; signed main () { std::ios::sync_with_stdio (false ); std::cin.tie (nullptr ); int n; std::cin >> n; std::vector<int > a (n + 1 ) ; for (int i = 0 ; i < n; i++) { int x; std::cin >> x; a[x] = i; } std::vector<i64> dp (n + 1 ) , cnt (n + 1 ) ; for (int i = 1 ; i <= n; i++) { std::vector<int > b; for (int j = i; j <= n; j += i) { b.emplace_back (a[j]); } auto c = b; std::sort (c.begin (), c.end ()); int m = b.size (); Fenwick<i64> fen (m) ; for (int j = m - 1 ; j >= 0 ; j--) { int x = std::lower_bound (c.begin (), c.end (), b[j]) - c.begin (); cnt[i] += fen.sum (x); fen.add (x, 1 ); } } for (int i = n; i; i--) { dp[i] = cnt[i]; for (int j = i + i; j <= n; j += i) { dp[i] -= dp[j]; } } std::cout << dp[1 ] << "\n" ; return 0 ; }