小奇遐想 (树状数组)

小奇遐想

时间限制: 1 Sec  内存限制: 128 MB
提交: 236  解决: 41
[提交] [状态] [讨论版] [命题人: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。

一个树状数组的简单题,写一下题解来祭奠我WA30+。

首先观察四个数,控制第一个,后面三个难以控制,控制第四个,结果同第一个。发现控制第二个的时候,可以知道他前面有多少个比他小的数,然后数组是全排列,那么后面比他小的数的个数就是a[i]-pre_min-1,后面数的个数有n-i个,减去比他小的,剩下的数就是比他大的数,然后将前面比他小的跟后面比他大的相乘,其中会得到很多c>d的,那样的话取后面比他大的数的时候加一个排列,去除c>d这种情况,搞定。还有 C n 2不用求逆元,也不知道为什么脑卡的要去求一个非质数的逆元。

代码实现:感受下我的极限压行

/*
Look at the star
Look at the shine for U
*/ 

#include<bits/stdc++.h>
#define sl(x) scanf("%lld",&x)
using namespace std;
typedef long long ll;
const int N = 1e6+5;
const ll mod = 16777216;
const ll INF = 1e18;
ll s[N],c[N],ml[N],mr[N],T[N],n;
ll lowbit(ll k) {return k&(-k);}
void add(ll x,ll k,ll *t) {while(x <= n){t[x] = (t[x]+k);x += lowbit(x);}}
ll query(ll k,ll *t) {ll ans = 0;while(k){ans = (ans+t[k]); k -= lowbit(k);}return ans;}
int main()
{
	ll i,j,k;
	sl(n);
	for(i = 1;i <= n;i++) sl(s[i]);
	for(i = 1;i <= n;i++) {ml[i] = query(s[i],c);mr[i] = s[i]-ml[i]-1;add(s[i],1,c);}
	ll sum1 = 0,sum2 = 0,x,y;
	for(i = 1;i <= n;i++) sum1 = (sum1+ml[i]*(n-i-mr[i])*(n-i-mr[i]-1)/2)%mod;
	for(i = 1;i <= n;i++) sum2 = (sum2+query(s[i],T)*(n-i-mr[i])%mod)%mod,add(s[i],ml[i],T);
	ll ans = (sum1-sum2+mod)%mod;
	printf("%lld\n",ans);
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值