题意:对于整数序列$A[1...n]$定义$f(l, r)$为区间$[l, r]$内等于区间最大值元素的个数,定义$z[i]$为所有满足$f(l, r)=i$的区间总数。对于所有的$1 leq i leq n$,计算$z[i]$。
分析:考虑由大往小枚举最大值,对于某一最大值为$M$的区间$[l, r)$,满足$a[p_i]=M$的元素将区间切割为若干子区间,那么这些子区间对长度的积对答案的某一项有等值的贡献,暴力枚举需要$O(n^2)$的时间,整体考虑那些对答案某一项有贡献的子区间对的积,它们满足卷积的性质。因此只需将长度序列与其反序列作类似多项式乘法的fft,即可将时间优化为$O(nlog(n))$。子区间递归处理即可。代码如下:
1 #include <algorithm> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <queue> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <ctime> 10 #include <cmath> 11 #include <iostream> 12 #include <assert.h> 13 #pragma comment(linker, "/STACK:102400000,102400000") 14 #define max(a, b) ((a) > (b) ? (a) : (b)) 15 #define min(a, b) ((a) < (b) ? (a) : (b)) 16 #define mp std :: make_pair 17 #define st first 18 #define nd second 19 #define keyn (root->ch[1]->ch[0]) 20 #define lson (u << 1) 21 #define rson (u << 1 | 1) 22 #define pii std :: pair<int, int> 23 #define pll pair<ll, ll> 24 #define pb push_back 25 #define type(x) __typeof(x.begin()) 26 #define foreach(i, j) for(type(j)i = j.begin(); i != j.end(); i++) 27 #define FOR(i, s, t) for(int i = (s); i <= (t); i++) 28 #define ROF(i, t, s) for(int i = (t); i >= (s); i--) 29 #define dbg(x) std::cout << x << std::endl 30 #define dbg2(x, y) std::cout << x << " " << y << std::endl 31 #define clr(x, i) memset(x, (i), sizeof(x)) 32 #define maximize(x, y) x = max((x), (y)) 33 #define minimize(x, y) x = min((x), (y)) 34 using namespace std; 35 typedef long long ll; 36 const int int_inf = 0x3f3f3f3f; 37 const ll ll_inf = 0x3f3f3f3f3f3f3f3f; 38 const int INT_INF = (int)((1ll << 31) - 1); 39 const double double_inf = 1e30; 40 const double eps = 1e-14; 41 typedef unsigned long long ul; 42 typedef unsigned int ui; 43 inline int readint(){ 44 int x; 45 scanf("%d", &x); 46 return x; 47 } 48 inline int readstr(char *s){ 49 scanf("%s", s); 50 return strlen(s); 51 } 52 53 class cmpt{ 54 public: 55 bool operator () (const int &x, const int &y) const{ 56 return x > y; 57 } 58 }; 59 60 int Rand(int x, int o){ 61 //if o set, return [1, x], else return [0, x - 1] 62 if(!x) return 0; 63 int tem = (int)((double)rand() / RAND_MAX * x) % x; 64 return o ? tem + 1 : tem; 65 } 66 void data_gen(){ 67 srand(time(0)); 68 freopen("in.txt", "w", stdout); 69 int kases = 20; 70 printf("%d ", kases); 71 while(kases--){ 72 int sz = 6e4; 73 printf("%d ", sz); 74 FOR(i, 1, sz) printf("%d ", Rand(sz, 1)); 75 printf(" "); 76 } 77 } 78 79 struct cmpx{ 80 bool operator () (int x, int y) { return x > y; } 81 }; 82 const int maxn = 6e4 + 10; 83 int a[maxn]; 84 int n; 85 struct Seg{ 86 int l, r, v; 87 }seg[maxn << 2]; 88 void build(int u, int l, int r){ 89 seg[u].l = l, seg[u].r = r; 90 if(seg[u].r - seg[u].l < 2){ 91 seg[u].v = l; 92 return; 93 } 94 int mid = (l + r) >> 1; 95 build(lson, l, mid), build(rson, mid, r); 96 if(a[seg[rson].v] > a[seg[lson].v]) seg[u].v = seg[rson].v; 97 else seg[u].v = seg[lson].v; 98 } 99 int query(int u, int l, int r){ 100 if(seg[u].l == l && seg[u].r == r) return seg[u].v; 101 int mid = (seg[u].l + seg[u].r) >> 1; 102 if(r <= mid) return query(lson, l, r); 103 else if(l >= mid) return query(rson, l, r); 104 int lhs = query(lson, l, mid), rhs = query(rson, mid, r); 105 if(a[rhs] > a[lhs]) return rhs; 106 return lhs; 107 } 108 int maxi; 109 vector<int> pos[maxn]; 110 int idx[maxn]; 111 void init(){ 112 maxi = -1; 113 FOR(i, 1, n) maximize(maxi, a[i]); 114 FOR(i, 1, maxi) pos[i].clear(); 115 FOR(i, 1, n){ 116 int sz = pos[a[i]].size(); 117 idx[i] = sz; 118 pos[a[i]].pb(i); 119 } 120 } 121 ll z[maxn]; 122 ll c[maxn], d[maxn], e[maxn << 1]; 123 int k; 124 const double PI = 2 * asin(1.); 125 struct Complex{ 126 double x, y; 127 Complex(double x = 0, double y = 0) : x(x), y(y) {} 128 }; 129 Complex operator + (const Complex &lhs, const Complex &rhs){ 130 return Complex(lhs.x + rhs.x, lhs.y + rhs.y); 131 } 132 Complex operator - (const Complex &lhs, const Complex &rhs){ 133 return Complex(lhs.x - rhs.x, lhs.y - rhs.y); 134 } 135 Complex operator * (const Complex &lhs, const Complex &rhs){ 136 double tl = lhs.x * rhs.x, tr = lhs.y * rhs.y, tt = (lhs.x + lhs.y) * (rhs.x + rhs.y); 137 return Complex(lhs.x * rhs.x - lhs.y * rhs.y, lhs.x * rhs.y + lhs.y * rhs.x); 138 } 139 Complex w[2][maxn << 2], x[maxn << 2], y[maxn << 2]; 140 141 void fft(Complex x[], int k, int v){ 142 int i, j, l; 143 Complex tem; 144 for(i = j = 0; i < k; i++){ 145 if(i > j) tem = x[i], x[i] = x[j], x[j] = tem; 146 for(l = k >> 1; (j ^= l) < l; l >>= 1) ; 147 } 148 for(i = 2; i <= k; i <<= 1) for(j = 0; j < k; j += i) for(l = 0; l < i >> 1; l++){ 149 tem = x[j + l + (i >> 1)] * w[v][k / i * l]; 150 x[j + l + (i >> 1)] = x[j + l] - tem; 151 x[j + l] = x[j + l] + tem; 152 } 153 } 154 int tot; 155 void solve(int l, int r){ 156 if(l >= r) return; 157 if(r - l == 1){ 158 ++z[1]; 159 return; 160 } 161 int p = query(1, l, r); 162 int tem = idx[p]; 163 int sz = pos[a[p]].size(); 164 k = 0; 165 c[k++] = p - l + 1; 166 while(tem + 1 < sz && pos[a[p]][tem + 1] < r) c[k++] = pos[a[p]][tem + 1] - pos[a[p]][tem], ++tem; 167 c[k++] = r - pos[a[p]][tem]; 168 ROF(i, k - 1, 0) d[i] = c[k - 1 - i]; 169 int len; 170 for(len = 1; len < (k << 1); len <<= 1) ; 171 FOR(i, 0, len) w[1][len - i] = w[0][i] = Complex(cos(PI * 2 * i / len), sin(PI * 2 * i / len)); 172 FOR(i, 0, k - 1) x[i] = Complex(c[i], 0); 173 FOR(i, k, len - 1) x[i] = Complex(0, 0); 174 fft(x, len, 0); 175 FOR(i, 0, k - 1) y[i] = Complex(d[i], 0); 176 FOR(i, k, len - 1) y[i] = Complex(0, 0); 177 fft(y, len, 0); 178 FOR(i, 0, len - 1) x[i] = x[i] * y[i]; 179 fft(x, len, 1); 180 FOR(i, 0, 2 * k - 2) e[i] = (ll)(x[i].x / len + .5); 181 FOR(i, 0, k - 2) z[k - 1 - i] += e[i]; 182 tem = idx[p]; 183 solve(l, p); 184 while(tem + 1 < sz && pos[a[p]][tem + 1] < r) solve(pos[a[p]][tem] + 1, pos[a[p]][tem + 1]), ++tem; 185 solve(pos[a[p]][tem] + 1, r); 186 } 187 int main(){ 188 //data_gen(); return 0; 189 //C(); return 0; 190 int debug = 0; 191 if(debug) freopen("in.txt", "r", stdin); 192 //freopen("out.txt", "w", stdout); 193 int T = readint(); 194 while(T--){ 195 n = readint(); 196 FOR(i, 1, n) a[i] = readint(); 197 build(1, 1, n + 1); 198 init(); 199 clr(z, 0); 200 tot = 0; 201 solve(1, n + 1); 202 ll ans = 0; 203 FOR(i, 1, n) ans += z[i] ^ i; 204 printf("%lld ", ans); 205 } 206 return 0; 207 }