叮叮猫 NKOJ P3722 (树状数组+容斥原理)

问题描述

【问题描述】    
   叮叮猫,学名蜻蜓,无脊椎动物。一般体型较大,翅膀长而窄,膜质,有清 晰的网状翅脉。
   有个叮叮猫飞到了nodgd房间里,nodgd赶紧用高速照相机连拍了?张清晰 的照片,以此分析叮叮猫的飞行轨迹。因为nodgd是个好人,所以在把数据给 你之前已经进行了离散化处理。简单地说,叮叮猫在第i张照片里飞行高度是ai, 其中所有ai都是1~n之间的整数(不一定是1~n的排列)。 nodgd定义了一种“欲扬先抑”的状态:如果存在三个整数i,j,k,满足条件1 ≤i<j<k≤n,且aj<ai<ak,就是欲扬先抑的。
    现在要求统计出有多少个这样的欲扬先抑三元组(i,j,k)

输入格式

第一行一个整数?,表示照片数。
第二行?个整数,表示每张照片里叮叮猫的飞行高度。 

输出格式


输出一行一个整数,表示欲扬先抑三元组的个数。 

样例输入

5
2 1 1 4 4

样例输出

4

提示

【数据范围】
对于30%的数据,n≤500;
对于50%的数据,n≤5000;
对于100%的数据,1≤n≤500000。 

 
 
就该打暴力对拍
对于最高点 求前面比他小的个数  总方案数为C(2 num)  即(n-1)*n/2
因为要满足 aj<ai<ak
所以得容斥一下 也就是减去 aj<=ai<ak  的情况
重新开一个树状数组 
每次记录 当前的高度 比他小的 数量 加上去  减去这个数量即可
 
code:
//
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
#define lowbit(i) i&(-i)
#define ll long long 
#define maxnn 501000
ll c[maxnn];
ll n;
ll a[maxnn];
ll c2[maxnn];
void modify1(ll x,ll d)
{
    for(int i=x; i<=n+100;i+=lowbit(i))
    {
        c2[i]+=d;
    }
}
void modify(ll x)
{
    for(int i=x; i<=n+100;i+=lowbit(i))
    {
        c[i]+=1;
    }
}
ll getsum(ll m)
{
    ll ans=0;
    for(int i=m;i;i-=lowbit(i))
    {
        ans+=c[i];
    }
    return ans;
}
ll getsum1(ll m)
{
    ll ans=0;
    for(int i=m;i;i-=lowbit(i))
    {
        ans+=c2[i];
    }
    return ans;
}
int main()
{

    //freopen("B.in","r",stdin);
    //freopen("B.out","w",stdout);
    cin>>n;
    ll ans=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
    }
    for(int i=1;i<=n;i++)
    {
        ans=ans+((getsum(a[i]-1))*(getsum(a[i]-1)-1))/2-(getsum1(a[i]-1));
        modify1(a[i],getsum(a[i]));    
        modify(a[i]);
    }
    printf("%lld",ans);
}

 

 

转载于:https://www.cnblogs.com/OIEREDSION/p/11314581.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值