题解 排列
正解是24分治
写的时候想对位置分段,但只会处理1234和4321
但其实可以同时对位置和值域分段
我们枚举两个数,尝试用这两个数将位置和值域都分成两段
发现除 \((1, 2)\ (1, 4)\ (3, 4)\) 外都满足这个性质
分段后就变成了在区间 \(l, r\) 内选一个值域在 \(a, b\) 内的数的方案数,可以二维前缀和实现
但刚才那种方法处理不了 \(2413\) 和 \(3142\)
对于 \(2143\),可以枚举3和4的位置,则问题转化为在两个区间内各选一个数,前面的数比后面的大的方案数
可以树状数组+广义扫描线实现
\(3142\) 把b数组reverse一下就是 \(2413\) 了
看起来非常令人愉悦的 Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 2010
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n;
int a[N], b[N];
namespace task1{
ll ans;
struct sub1{
int bin[N], bin2[N];
void upd(int i, int dat) {for (; i<=n; i+=i&-i) bin[i]+=dat;}
int qcnt(int i) {int ans=0; for (; i; i-=i&-i) ans+=bin[i]; return ans;}
void upd2(int i, int dat) {for (; i<=n; i+=i&-i) bin2[i]+=dat;}
int qans(int i) {int ans=0; for (; i; i-=i&-i) ans+=bin2[i]; return ans;}
void clear() {
memset(bin, 0, sizeof(bin));
memset(bin2, 0, sizeof(bin2));
}
void add(int dat) {
int tem=qcnt(dat);
upd(dat, 1);
upd2(dat, tem);
}
int query(int val) {return qans(val);}
}t1;
struct sub2{
int bin[N], bin2[N];
void upd(int i, int dat) {for (; i; i-=i&-i) bin[i]+=dat;}
int qcnt(int i) {int ans=0; for (; i<=n; i+=i&-i) ans+=bin[i]; return ans;}
void upd2(int i, int dat) {for (; i; i-=i&-i) bin2[i]+=dat;}
int qans(int i) {int ans=0; for (; i<=n; i+=i&-i) ans+=bin2[i]; return ans;}
void clear() {
memset(bin, 0, sizeof(bin));
memset(bin2, 0, sizeof(bin2));
}
void add(int dat) {
int tem=qcnt(dat);
upd(dat, 1);
upd2(dat, tem);
}
int query(int val) {return qans(val);}
}t2;
void solve() {
for (int i=2; i<=2; ++i) {
t1.clear(); t2.clear();
for (int j=1; j<=i; ++j) t1.add(b[j]);
for (int j=n; j>i; --j) t2.add(b[j]);
for (int j=1; j<=n; ++j) {
cout<<"j: "<<j<<' '<<t1.query(j)<<' '<<t2.query(j)<<endl;
ans+=t1.query(j)*t2.query(j);
}
}
printf("%lld\n", ans);
exit(0);
}
}
namespace task2{
ll dp[N][5], ans;
void solve() {
for (int i=1; i<=n; ++i) dp[i][1]=1;
for (int i=1; i<=n; ++i) {
for (int k=1; k<i; ++k) if (b[k]<b[i]) {
for (int j=2; j<=4; ++j) {
dp[i][j]+=dp[k][j-1];
}
}
}
for (int i=1; i<=n; ++i) ans+=dp[i][4];
printf("%lld\n", ans);
exit(0);
}
}
namespace task3{
ll ans;
void dfs(int u, vector<int> v) {
if (v.size()==4) {++ans; return ;}
for (int i=u; i<=n; ++i) {
v.push_back(b[i]);
int t=v.size();
for (int j=1; j<=t; ++j) {
for (int k=j+1; k<=t; ++k) {
if ((a[j]-a[k])*(v[j-1]-v[k-1])<=0) goto jump;
}
}
dfs(i+1, v);
jump: ;
v.pop_back();
}
}
void solve() {
dfs(1, vector<int>());
printf("%lld\n", ans);
exit(0);
}
}
namespace task{
int sum[N][N], bin1[N], bin2[N];
inline int query(int l1, int r1, int l2, int r2) {return sum[r1][r2]-sum[l1-1][r2]-sum[r1][l2-1]+sum[l1-1][l2-1];}
inline void upd1(int i, int dat) {for (; i; i-=i&-i) bin1[i]+=dat;}
inline int query1(int i) {int ans=0; for (; i<=n; i+=i&-i) ans+=bin1[i]; return ans;}
inline void upd2(int i, int dat) {for (; i<=n; i+=i&-i) bin2[i]+=dat;}
inline int query2(int i) {int ans=0; for (; i; i-=i&-i) ans+=bin2[i]; return ans;}
void solve() {
int it=0;
for (int i=1; i<=4; ++i) it=it*10+a[i];
for (int i=1; i<=n; ++i) sum[i][b[i]]=1;
for (int i=1; i<=n; ++i)
for (int j=1; j<=n; ++j)
sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
ll ans=0, now;
switch (it) {
case 1234: for (int i=2; i<n; ++i) for (int j=i+2; j<=n; ++j) if (b[i]<b[j]-1) ans+=query(1, i-1, 1, b[i]-1)*query(i+1, j-1, b[i]+1, b[j]-1); break;
case 1243: for (int i=2; i<n; ++i) for (int j=i+1; j<n; ++j) if (b[i]<b[j]-1) ans+=query(1, i-1, 1, b[i]-1)*query(j+1, n, b[i]+1, b[j]-1); break;
case 1324: for (int i=2; i<n; ++i) for (int j=i+1; j<n; ++j) if (b[i]>b[j]) ans+=query(1, i-1, 1, b[j]-1)*query(j+1, n, b[i]+1, n); break;
case 1342: for (int i=2; i<n; ++i) for (int j=i+2; j<=n; ++j) if (b[i]>b[j]) ans+=query(1, i-1, 1, b[j]-1)*query(i+1, j-1, b[i]+1, n); break;
case 1423: for (int i=2; i<n; ++i) for (int j=i+1; j<n; ++j) if (b[i]>b[j]+1) ans+=query(1, i-1, 1, b[j]-1)*query(j+1, n, b[j]+1, b[i]-1); break;
case 1432: for (int i=2; i<n; ++i) for (int j=i+2; j<=n; ++j) if (b[i]>b[j]+1) ans+=query(1, i-1, 1, b[j]-1)*query(i+1, j-1, b[j]+1, b[i]-1); break;
case 2134: for (int i=1; i<n; ++i) for (int j=i+2; j<n; ++j) if (b[i]<b[j]) ans+=query(i+1, j-1, 1, b[i]-1)*query(j+1, n, b[j]+1, n); break;
case 2143: for (int i=1; i<n; ++i) for (int j=i+2; j<n; ++j) if (b[i]<b[j]-1) ans+=query(i+1, j-1, 1, b[i]-1)*query(j+1, n, b[i]+1, b[j]-1); break;
case 2314: for (int i=2; i<n; ++i) for (int j=i+1; j<n; ++j) if (b[i]>b[j]+1) ans+=query(1, i-1, b[j]+1, b[i]-1)*query(j+1, n, b[i]+1, n); break;
case 2341: for (int i=1; i<n; ++i) for (int j=i+2; j<n; ++j) if (b[j]>b[i]+1) ans+=query(i+1, j-1, b[i]+1, b[j]-1)*query(j+1, n, 1, b[i]-1); break;
case 2431: for (int i=1; i<n; ++i) for (int j=i+2; j<n; ++j) if (b[i]<b[j]) ans+=query(i+1, j-1, b[j]+1, n)*query(j+1, n, 1, b[i]-1); break;
case 3124: for (int i=1; i<n; ++i) for (int j=i+2; j<n; ++j) if (b[i]>b[j]) ans+=query(i+1, j-1, 1, b[j]-1)*query(j+1, n, b[i]+1, n); break;
case 3214: for (int i=1; i<n; ++i) for (int j=i+2; j<n; ++j) if (b[i]>b[j]+1) ans+=query(i+1, j-1, b[j]+1, b[i]-1)*query(j+1, n, b[i]+1, n); break;
case 3241: for (int i=2; i<n; ++i) for (int j=i+1; j<n; ++j) if (b[i]<b[j]) ans+=query(1, i-1, b[i]+1, b[j]-1)*query(j+1, n, 1, b[i]-1); break;
case 3412: for (int i=1; i<n; ++i) for (int j=i+2; j<n; ++j) if (b[i]>b[j]+1) ans+=query(i+1, j-1, b[i]+1, n)*query(j+1, n, b[j]+1, b[i]-1); break;
case 3421: for (int i=2; i<n; ++i) for (int j=i+1; j<n; ++j) if (b[i]>b[j]) ans+=query(1, i-1, b[j]+1, b[i]-1)*query(j+1, n, 1, b[j]-1); break;
case 4123: for (int i=1; i<n; ++i) for (int j=i+2; j<n; ++j) if (b[i]>b[j]+1) ans+=query(i+1, j-1, 1, b[j]-1)*query(j+1, n, b[j]+1, b[i]-1); break;
case 4132: for (int i=2; i<n; ++i) for (int j=i+1; j<n; ++j) if (b[i]<b[j]-1) ans+=query(1, i-1, b[j]+1, n)*query(j+1, n, b[i]+1, b[j]-1); break;
case 4213: for (int i=2; i<n; ++i) for (int j=i+2; j<=n; ++j) if (b[i]<b[j]) ans+=query(1, i-1, b[j]+1, n)*query(i+1, j-1, 1, b[i]-1); break;
case 4231: for (int i=2; i<n; ++i) for (int j=i+1; j<n; ++j) if (b[i]<b[j]) ans+=query(1, i-1, b[j]+1, n)*query(j+1, n, 1, b[i]-1); break;
case 4312: for (int i=2; i<n; ++i) for (int j=i+1; j<n; ++j) if (b[i]>b[j]+1) ans+=query(1, i-1, b[i]+1, n)*query(j+1, n, b[j]+1, b[i]-1); break;
case 4321: for (int i=2; i<n; ++i) for (int j=i+1; j<n; ++j) if (b[i]>b[j]) ans+=query(1, i-1, b[i]+1, n)*query(j+1, n, 1, b[j]-1); break;
case 3142: reverse(b+1, b+n+1); case 2413:
for (int i=4; i<=n; ++i) {
now=0;
memset(bin1, 0, sizeof(bin1));
memset(bin2, 0, sizeof(bin2));
for (int j=2; j<i; ++j) if (b[j]<b[i]) upd2(b[j], 1);
for (int j=2; j<i-1; ++j) {
if (b[j]<b[i]) {now-=query1(b[j]); upd2(b[j], -1);}
if (b[j-1]<b[i]) {now+=query2(b[j-1]); upd1(b[j-1], 1);}
if (b[j]>b[i]) ans+=now;
}
}
}
printf("%lld\n", ans);
exit(0);
}
}
signed main()
{
freopen("c.in", "r", stdin);
freopen("c.out", "w", stdout);
n=read();
for (int i=1; i<=4; ++i) a[i]=read();
for (int j=1; j<=n; ++j) b[j]=read();
#if 0
if (a[1]==1 && a[2]==2 && a[3]==3 && a[4]==4) task2::solve();
else if (a[1]==4 && a[2]==3 && a[3]==2 && a[4]==1) {
for (int j=1; j<=n; ++j) b[j]=-b[j];
task2::solve();
}
task3::solve();
#endif
task::solve();
return 0;
}