5727: 小奇遐想
时间限制: 1 Sec 内存限制: 128 MB
提交: 285 解决: 58
[提交] [状态] [讨论版] [命题人:admin]
题目描述
撷来一缕清风飘渺
方知今日书信未到
窗外三月天霁垂柳新长枝条
风中鸟啼犹带欢笑
——《清风醉梦》
小奇望着青天中的悠悠白云,开始了无限的遐想,在它的视野中,恰好有n朵高度不同的白云排成一排,他想从左到右选出四朵白云a,b,c,d,使得h_a<h_b<h_d<h_c,即看起来像是彩虹的形状!它想知道有多少种方案数。
输入
第一行包括1个整数n。
第二行包括n个整数,第i个正数表示h_i,保证这n个整数是n的一个全排列。
输出
输出一个整数表示答案。(mod 16777216)
样例输入
5 1 5 3 2 4
样例输出
0
提示
对于10%的数据n<=600;对于40%的数据n<=5000;
对于100%的数据n<=200000。
很简单,寻找1243这种序列直接找很难找到,所以需要容斥一下,即先找12xx这种序列只要XX都大于2即可,然后找到1234这种序列,那么用12xx-1234就是1243的答案。两遍树状数组查找。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define FIN freopen("D://code//in.txt", "r", stdin)
#define ppr(i,x,n) for(int i = x;i <= n;i++)
#define rpp(i,n,x) for(int i = n;i >= x;i--)
const double eps = 1e-8;
const int mod = 16777216;
const int maxn = 5e5+10;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
inline int read() {//读入挂
int ret = 0, c, f = 1;
for(c = getchar(); !(isdigit(c) || c == '-'); c = getchar());
if(c == '-') f = -1, c = getchar();
for(; isdigit(c); c = getchar()) ret = ret * 10 + c - '0';
if(f < 0) ret = -ret;
return ret;
}
ll front[maxn],back[maxn];//分别记录当前位置前面比他小的有多少个,后面比他大的有多好个
ll a[maxn];
ll c[maxn];
ll n,ans1,ans2,ans;//ans1表示12xx个数ans2表示1234的个数最后ans=ans1-ans2为答案
ll lowbit(ll x)
{
return x&(-x);
}
ll sum(ll k)
{
ll ans = 0;
while(k > 0)
{
ans += c[k];
k -= lowbit(k);
}
return ans;
}
void add(ll k,ll x)
{
while(k <= n)
{
c[k] += x;
k += lowbit(k);
}
}
int main()
{
IO;
cin>>n;ans1=0;ans2=0;
ppr(i,1,n) {cin>>a[i];front[i]=sum(a[i]);add(a[i],1);}
memset(c,0,sizeof(c));
rpp(i,n,1) {back[i]=sum(n)-sum(a[i]);add(a[i],1);}
//ppr(i,1,n) cout<<front[i]<<" "<<back[i]<<endl;
ppr(i,1,n){ans1+=front[i]*(back[i]*(back[i]-1)/2);ans1%=mod;}
memset(c,0,sizeof(c));
ppr(i,1,n){ans2+=sum(a[i])*back[i];ans2%=mod;add(a[i],front[i]);}
//cout<<ans1<<" "<<ans2<<endl;
ans=(ans1-ans2+mod)%mod;
cout<<ans<<endl;
}