P - 浑身难受
maya,camp上搬来的神题,作为一名智障
一共二十四种情况,然后每种倒序一下可以得到另外一种,所以可以简化成12种,然后我这个智障就写了十二种,
首先分为3类,
1, 1和4不相连,就n^2枚举2和3的位置,然后1和4的所在的区间用按值树状数组维护,1那里就是查询区间有多少比个比2小的值,4那里就是查询有多少个比3大的值(总点数减去<=3的就是啦),然后乘一下就可以
2, 1,3不相连,就n^2枚举2和4的位置,然后1和3的所在的区间用按值树状数组维护,1那里就是查询区间有多少比个比2小的值,3那里就是查询有多少个比4小的减去有多少个比3小的,然后乘一下就可以
3, 2,4不连在一起,把序列翻转一下,就是A[i]=5-A[i],p[i]=N+1-p[i],翻转完之后就是1和3不连在一起,然后就可以用2来做了
4, 2413,这种题解写的是2413=24xx-2411-2433-2431,一开始没想明白,然后我就枚举3和4做的,然后2和1那里就分别统计比3小的有多少个,因为两数不可能相等,所以要么就是1423,要么就是2413,然后算出来之后,减去1423,就是2413的个数
后来想明白了题解的做法,主要题解提到了2433和2411,一开始以为是0,后来发现不是0,33表示两个数都在2和4之间,11表示两个数都比2小
具体做法就是枚举2和4的位置,固定2和4之后,要枚举1和3,因为只知道1和3都比4小,然后分为三种情况 (实际上是4种)
1,枚举的两个数都比2小,这个你是能算出来的,相当于2411
2,枚举的两个数都在2和4之间,这个也是能算出来的,相当于2433
3,枚举的两个数,一个比2小,一个在2和4之间,这个相当于是2413+2431
所以2413=24xx-2411-2433-2431
这题,真是做的浑身难受,300行代码怼过去了
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define ll long long #define maxn 2005 int N, A[4], p[maxn]; int BIT1[maxn], BIT2[maxn]; ll query(int tree[], int i) { ll sum = 0; while (i) { sum += tree[i]; i -= i&(-i); } return sum; } void update(int tree[], int i, int val) { if (i == 0) return; while (i <= N) { tree[i] += val; i += i&(-i); } } ll No1234()//枚举23位置 { ll sum = 0; for (int i = 2; i <= N - 2; ++i)//i是2,j是3 { update(BIT1, p[i - 1], 1); memset(BIT2, 0, sizeof(int)*maxn); for (int j = N - 1; j >= i + 1; --j) { update(BIT2, p[j + 1], 1); if (p[i] < p[j]) sum += query(BIT1, p[i])*(N - j - query(BIT2, p[j])); } } return sum; } ll No1243()//枚举23位置 { ll sum = 0; for (int i = 2; i <= N - 2; ++i)//i是2,j是3 { update(BIT1, p[i - 1], 1); memset(BIT2, 0, sizeof(int)*maxn); for (int j = i + 2; j <= N; ++j) { update(BIT2, p[j - 1], 1); if (p[i] < p[j]) sum += query(BIT1, p[i])*(j - i - 1 - query(BIT2, p[j])); } } return sum; } ll No1324()//枚举23位置 { ll sum = 0; for (int i = 2; i <= N - 2; ++i)//i是3,j是2 { update(BIT1, p[i - 1], 1); memset(BIT2, 0, sizeof(int)*maxn); for (int j = N - 1; j >= i + 1; --j) { update(BIT2, p[j + 1], 1); if (p[i] > p[j]) sum += (N - j - query(BIT2, p[i]))*query(BIT1, p[j]); } } return sum; } ll No1342()//枚举23位置 { ll sum = 0; for (int i = 2; i <= N - 2; ++i)//i是3,j是2 { update(BIT1, p[i - 1], 1); memset(BIT2, 0, sizeof(int)*maxn); for (int j = i + 2; j <= N; ++j) { update(BIT2, p[j - 1], 1); if (p[i] > p[j]) sum += query(BIT1, p[j])*(j - i - 1 - query(BIT2, p[i])); } } return sum; } ll No1423()//枚举24位置 { ll sum = 0; for (int i = 2; i <= N - 2; ++i)//i是4,j是2 { update(BIT1, p[i - 1], 1); memset(BIT2, 0, sizeof(int)*maxn); for (int j = N - 1; j >= i + 1; --j) { update(BIT2, p[j + 1], 1); if (p[i] > p[j]) sum += query(BIT1, p[j])*(query(BIT2, p[i]) - query(BIT2, p[j])); } } return sum; } ll No1432()//枚举24位置 { ll sum = 0; for (int i = 2; i <= N - 2; ++i)//i是4,j是2 { update(BIT1, p[i - 1], 1); memset(BIT2, 0, sizeof(int)*maxn); for (int j = i + 2; j <= N; ++j) { update(BIT2, p[j - 1], 1); if (p[i] > p[j]) { sum += query(BIT1, p[j])*(query(BIT2, p[i]) - query(BIT2, p[j])); } } } return sum; } ll No2134()//枚举23位置 { ll sum = 0; for (int i = N - 1; i >= 3; --i)//i是3,j是2 { update(BIT1, p[i + 1], 1); memset(BIT2, 0, sizeof(int)*maxn); for (int j = i - 2; j >= 1; --j) { update(BIT2, p[j + 1], 1); if (p[i] > p[j]) sum += (N - i - query(BIT1, p[i]))*query(BIT2, p[j]); } } return sum; } ll No2143()//枚举24位置 { ll sum = 0; for (int i = N - 1; i >= 3; --i)//i是4,j是2 { update(BIT1, p[i + 1], 1); memset(BIT2, 0, sizeof(int)*maxn); for (int j = i - 2; j >= 1; --j) { update(BIT2, p[j + 1], 1); if (p[i] > p[j]) sum += (query(BIT1, p[i]) - query(BIT1, p[j])) * query(BIT2, p[j]); } } return sum; } ll No2314()//先翻转,再枚举24位置 { //翻转后是3241,再倒序一下,是1423 ll sum = 0; for (int i = 1; i <= N; ++i) p[i] = N + 1 - p[i]; for (int i = 1; i <= N / 2; ++i) { int t; t = p[i]; p[i] = p[N + 1 - i]; p[N + 1 - i] = t; } sum = No1423(); return sum; } ll No2413()//暴力枚举3和4,树状数组维护1和2的数,x4x3-1423=2413 { ll sum = 0; for (int i = 2; i <= N - 2; ++i)//i是4,j是3 { update(BIT1, p[i - 1], 1); memset(BIT2, 0, sizeof(int)*maxn); for (int j = i + 2; j <= N; ++j) { update(BIT2, p[j - 1], 1); if (p[i] > p[j]) { sum += query(BIT1, p[j])*query(BIT2, p[j]); } } } memset(BIT1, 0, sizeof(int)*maxn); memset(BIT2, 0, sizeof(int)*maxn); sum -= No1423(); return sum; } ll No3124()//枚举2和3的位置 { ll sum = 0; for (int i = N - 1; i >= 3; --i)//i是2,j是3 { update(BIT1, p[i + 1], 1); memset(BIT2, 0, sizeof(int)*maxn); for (int j = i - 2; j >= 1; --j) { update(BIT2, p[j + 1], 1); if (p[j] > p[i]) sum += (N - i - query(BIT1, p[j]))*query(BIT2, p[i]); } } return sum; } ll No3214()//枚举2和4的位置 { ll sum = 0; for (int i = 2; i <= N - 2; ++i)//i是2,j是4 { update(BIT1, p[i - 1], 1); memset(BIT2, 0, sizeof(int)*maxn); for (int j = i + 2; j <= N; ++j) { update(BIT2, p[j - 1], 1); if (p[i] < p[j]) sum += (query(BIT1, p[j]) - query(BIT1, p[i]))*query(BIT2, p[i]); } } return sum; } void deal_A() { int x = A[0] * 1000 + A[1] * 100 + A[2] * 10 + A[3]; if (x == 2341 || x == 2431 || x == 3142 || x == 3241 || x == 3412 || x == 3421 || x == 4123 || x == 4132 || x == 4213 || x == 4231 || x == 4312 || x == 4321) { int t; t = A[0]; A[0] = A[3]; A[3] = t; t = A[1]; A[1] = A[2]; A[2] = t; for (int i = 1; i <= N / 2; ++i) { t = p[i]; p[i] = p[N + 1 - i]; p[N + 1 - i] = t; } } } ll compute() { int x = A[0] * 1000 + A[1] * 100 + A[2] * 10 + A[3]; if (x == 1234) return No1234(); if (x == 1243) return No1243(); if (x == 1324) return No1324(); if (x == 1342) return No1342(); if (x == 1423) return No1423(); if (x == 1432) return No1432(); if (x == 2134) return No2134(); if (x == 2143) return No2143(); if (x == 2314) return No2314(); if (x == 2413) return No2413(); if (x == 3124) return No3124(); if (x == 3214) return No3214(); return -1; } int main() { //freopen("input.txt", "r", stdin); scanf("%d", &N); for (int i = 0; i < 4; ++i) scanf("%d", &A[i]); for (int i = 1; i <= N; ++i) scanf("%d", &p[i]); if (N < 4) printf("0\n"); else { deal_A(); ll ans = compute(); printf("%lld\n", ans); } //system("pause"); //while (1); return 0; }