1. 程式人生 > >洛谷P4135 作詩

洛谷P4135 作詩

ble 前綴 opened style -o2 work 在線 aps time

題意:[l,r]之間有多少個數出現了正偶數次。強制在線。

解:第一眼想到莫隊,然後發現強制在線...分塊吧。

有個很樸素的想法就是蒲公英那題的套路,做每塊前綴和的桶。

然後發現這題空間128M,數組大小我的是133M......看到有人卡到了122M,但是我又不想冒險,就換寫法了。(題解裏全是空間n1.5的...)

那就用蒲公英的另一個套路吧。。。vector + 二分。

預處理出每兩個塊之間的答案,然後查詢的時候對邊角掃一遍,每個數vector二分,求得出現幾次,統計答案。

這樣一來塊大小是(n/logn)0.5的,然後交上去發現T成10分...自閉了。

YY出了個做法,每個數維護是第幾個出現的該數值的數,然後發現對於某種數值只出現在一邊邊角的話,不會處理,又只會vector了...雖然還可以值域分塊做到log(n0.5

),但是感覺上沒啥太大優化,懶得寫了...

把之前的10分代碼玄學調了一波塊大小,然後吸氧,居然A了。。。。。。自閉了。

技術分享圖片
  1 // luogu-judger-enable-o2
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <vector>
  5 #include <cmath>
  6 
  7 const int N = 100010;
  8 
  9 int bin[N], a[N], sum[1400][1400], n, lm, le[N], re[N], fr[N];
 10
std::vector<int> v[N]; 11 bool vis[N]; 12 13 inline void read(int &x) { 14 x = 0; 15 char c = getchar(); 16 while(c < 0 || c > 9) { 17 c = getchar(); 18 } 19 while(c >= 0 && c <= 9) { 20 x = (x << 3) + (x << 1
) + c - 48; 21 c = getchar(); 22 } 23 return; 24 } 25 26 inline int getTime(int x, int y, int c) { 27 if(x > y) { 28 return 0; 29 } 30 x = std::lower_bound(v[c].begin(), v[c].end(), x) - v[c].begin(); 31 y = std::upper_bound(v[c].begin(), v[c].end(), y) - v[c].begin() - 1; 32 return y - x + 1; 33 } 34 35 inline int ask(int x, int y) { 36 int l = fr[x], r = fr[y], ans = 0; 37 if(l == r) { 38 for(int k = x; k <= y; k++) { 39 if(bin[a[k]]) { 40 bin[a[k]] & 1 ? ans++ : ans--; 41 } 42 bin[a[k]]++; 43 } 44 for(int k = x; k <= y; k++) { 45 bin[a[k]]--; 46 } 47 return ans; 48 } 49 for(int k = x; k <= re[l]; k++) { 50 bin[a[k]]++; 51 } 52 for(int k = le[r]; k <= y; k++) { 53 bin[a[k]]++; 54 } 55 for(int k = x; k <= re[l]; k++) { 56 if(vis[a[k]]) { 57 continue; 58 } 59 vis[a[k]] = 1; 60 if(bin[a[k]] & 1) { 61 int t = getTime(le[l + 1], re[r - 1], a[k]); 62 if(t) { 63 ans += t & 1 ? 1 : -1; 64 } 65 } 66 else { 67 ans += getTime(le[l + 1], re[r - 1], a[k]) == 0; 68 } 69 } 70 for(int k = le[r]; k <= y; k++) { 71 if(vis[a[k]]) { 72 continue; 73 } 74 vis[a[k]] = 1; 75 if(bin[a[k]] & 1) { 76 int t = getTime(le[l + 1], re[r - 1], a[k]); 77 if(t) { 78 ans += t & 1 ? 1 : -1; 79 } 80 } 81 else { 82 ans += getTime(le[l + 1], re[r - 1], a[k]) == 0; 83 } 84 } 85 for(int k = x; k <= re[l]; k++) { 86 vis[a[k]] = 0; 87 bin[a[k]]--; 88 } 89 for(int k = le[r]; k <= y; k++) { 90 vis[a[k]] = 0; 91 bin[a[k]]--; 92 } 93 return ans + sum[l + 1][r - 1]; 94 } 95 96 int main() { 97 int m; 98 read(n); 99 read(lm); 100 read(m); 101 int T = sqrt((double)(n) / log2(n) * 2); 102 for(int i = 1; i <= n; i++) { 103 read(a[i]); 104 v[a[i]].push_back(i); 105 fr[i] = (i - 1) / T + 1; 106 } 107 // prework 108 for(int i = 1; i <= fr[n]; i++) { 109 le[i] = re[i - 1] + 1; 110 re[i] = le[i] + T - 1; 111 if(i == fr[n]) { 112 re[i] = n; 113 } 114 } 115 116 for(int l = 1; l <= fr[n]; l++) { 117 int ans = 0; 118 for(int r = l; r <= fr[n]; r++) { 119 for(int k = le[r]; k <= re[r]; k++) { 120 if(bin[a[k]]) { 121 bin[a[k]] & 1 ? ans++ : ans--; 122 } 123 bin[a[k]]++; 124 } 125 sum[l][r] = ans; 126 } 127 for(int k = le[l]; k <= n; k++) { 128 bin[a[k]]--; 129 } 130 } 131 132 int lastans = 0; 133 for(int i = 1, x, y; i <= m; i++) { 134 read(x); 135 read(y); 136 x = (x + lastans) % n + 1; 137 y = (y + lastans) % n + 1; 138 if(x > y) { 139 std::swap(x, y); 140 } 141 lastans = ask(x, y); 142 printf("%d\n", lastans); 143 } 144 145 return 0; 146 }
AC代碼

洛谷P4135 作詩