fork download
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. using ll = long long;
  4.  
  5. struct Fenwick {
  6. int n;
  7. vector<int> bit;
  8. Fenwick(int n=0){init(n);}
  9. void init(int n_){
  10. n = n_;
  11. bit.assign(n+1, 0);
  12. }
  13. void add(int i, int v){
  14. for(; i<=n; i += i&-i) bit[i] += v;
  15. }
  16. int sumPrefix(int i){
  17. int s=0;
  18. for(; i>0; i -= i&-i) s += bit[i];
  19. return s;
  20. }
  21. int sumRange(int l, int r){
  22. if(r<l) return 0;
  23. return sumPrefix(r) - sumPrefix(l-1);
  24. }
  25. };
  26.  
  27. int main(){
  28. ios::sync_with_stdio(false);
  29. cin.tie(nullptr);
  30. int N;
  31. if(!(cin >> N)) return 0;
  32. vector<int> A(N+1);
  33. int maxA = 0;
  34. for(int i=1;i<=N;i++){ cin >> A[i]; maxA = max(maxA, A[i]); }
  35.  
  36. // positions per value
  37. int V = maxA;
  38. vector<vector<int>> pos(V+1);
  39. for(int i=1;i<=N;i++){
  40. pos[A[i]].push_back(i);
  41. }
  42.  
  43. const int B = 700; // threshold ~ sqrt(N)
  44. ll total = (ll)N * (N+1) / 2;
  45. ll bad = 0; // number of subarrays that have a majority (to be subtracted)
  46.  
  47. // 1) Heavy values (freq > B)
  48. for(int val = 1; val <= V; ++val){
  49. int k = (int)pos[val].size();
  50. if(k <= B) continue;
  51. // build prefix S: +1 if A[i]==val else -1
  52. vector<int> S(N+1);
  53. S[0] = 0;
  54. for(int i=1;i<=N;i++){
  55. S[i] = S[i-1] + (A[i]==val ? 1 : -1);
  56. }
  57. // coordinate compress S values
  58. vector<int> comp = S;
  59. sort(comp.begin(), comp.end());
  60. comp.erase(unique(comp.begin(), comp.end()), comp.end());
  61. int m = (int)comp.size();
  62. Fenwick fw(m+5);
  63. // count pairs i<j with S[j] > S[i]
  64. for(int i=0;i<=N;i++){
  65. int id = int(lower_bound(comp.begin(), comp.end(), S[i]) - comp.begin()) + 1;
  66. // number of previous S < S[i] = sum of indices < id
  67. bad += fw.sumPrefix(id-1);
  68. fw.add(id, 1);
  69. }
  70. }
  71.  
  72. // 2) Light values (freq <= B)
  73. // For each value, consider windows of t consecutive occurrences
  74. for(int val = 1; val <= V; ++val){
  75. int k = (int)pos[val].size();
  76. if(k == 0 || k > B) continue;
  77. // create augmented pos with boundaries
  78. vector<int> p;
  79. p.reserve(k+2);
  80. p.push_back(0);
  81. for(int x: pos[val]) p.push_back(x);
  82. p.push_back(N+1);
  83. // p indices: 0..k+1, actual occurrences at 1..k
  84. // iterate t = number of occurrences inside subarray
  85. for(int t = 1; t <= k; ++t){
  86. // slide window of length t over occurrences
  87. for(int i = 1; i + t - 1 <= k; ++i){
  88. int left_prev = p[i-1];
  89. int left_first = p[i];
  90. int right_last = p[i+t-1];
  91. int right_next = p[i+t];
  92. // L in [left_prev+1, left_first]
  93. int Lstart = left_prev + 1;
  94. int Lend = left_first;
  95. if(Lstart > Lend) continue;
  96. // R min = right_last
  97. int Rmin = right_last;
  98. int Rmax_cap = right_next - 1;
  99. if(Rmin > Rmax_cap) continue; // no valid R at all
  100. // for given L, Rmax = min(Rmax_cap, L + 2t - 2)
  101. // Count_R = max(0, Rmax - Rmin + 1)
  102. // We sum Count_R for L in [Lstart..Lend]
  103. long long Cconst = (long long)(2*t - 1 - Rmin); // Count_R = L + Cconst when L+2t-2 <= Rmax_cap
  104. // D = Rmax_cap - (2t-2) : threshold L where L+2t-2 >= Rmax_cap
  105. int D = Rmax_cap - (2*t - 2);
  106. // range1: L in [L1..L2] where L <= min(Lend, D) and also L >= Lstart and L >= L_lower_bound so that Count_R>0
  107. int L1 = max(Lstart, Rmin - (2*t - 2)); // ensure L+2t-2 >= Rmin -> Count_R positive
  108. int L2 = min(Lend, D);
  109. long long sum = 0;
  110. if(L1 <= L2){
  111. // sum_{L=L1..L2} (L + Cconst) = sum L + (L2-L1+1)*Cconst
  112. long long cnt = L2 - L1 + 1;
  113. long long sumL = (long long)(L1 + L2) * cnt / 2;
  114. sum += sumL + cnt * Cconst;
  115. }
  116. // range2: L in [max(Lstart, D+1) .. Lend], Count_R = Rmax_cap - Rmin +1 (if positive)
  117. int L3 = max(Lstart, D+1);
  118. int L4 = Lend;
  119. if(L3 <= L4){
  120. long long cnt = L4 - L3 + 1;
  121. long long valR = Rmax_cap - Rmin + 1;
  122. if(valR > 0) sum += cnt * valR;
  123. }
  124. if(sum > 0) bad += sum;
  125. }
  126. }
  127. }
  128.  
  129. ll good = total - bad;
  130. cout << good << '\n';
  131. return 0;
  132. }
  133.  
Success #stdin #stdout 0s 5320KB
stdin
4
2 1 1 3
stdout
3