题目大意:

Given a sequence A with length n,count how many quadruple (a,b,c,d) satisfies: a≠b≠c≠d,1≤a<b≤n,1≤c<d≤n,Aa<Ab,Ac>Ada≠b≠c≠d,1≤a<b≤n,1≤c<d≤n,Aa<Ab,Ac>Ad.

A1,A2⋯AnA1,A2⋯An.  1≤n≤500001≤n≤50000  0≤Ai≤1e9

基本思路:

最朴素的思想就是算出所有顺序对所有逆序对相乘然后再减去所有有重复元素的结果,最终得到答案;

将原数组排序后去重然后从1开始标号(离散化),然后线段树维护某个标号有多少个数;

min_[i]:表示原数组下标在1~i-1的数比下标为i的数小的数的个数;

max_[i]:表示原数组下标在1~i-1的数比下标为i的数大的数的个数;

hmin_[i]:表示原数组下标在i之后的数比下标为i的数小的数的个数;

hmax_[i]:表示原数组下标在i之后的数比下标为i的数大的数的个数;

num[i]:树状数组的维护数组;

sum[i]:表示到下标为i的数中,从中任意挑出两个数满足下标小的数小于下标大的数的个数;

接下来枚举当前ai作为Vd,那么就存在mx[i]个Vc,以及sum[n]对Va,Vb。res+=mx[i]*sum[n]

由于答案会多算进去a=c || a=d || b=c || b=d的情况,那么枚举这四种情况减去就可以了,a=c那么必定b!=d,同理其他

a=c:ans-=hmn[i]*hmx[i]

a=d:ans-=mx[i]*hmx[i]

b=c:ans-=mn[i]*hmn[i]

b=d:ans-=mx[i]*mn[i]

反思与总结:

//对于树状数组,我一直有所顾忌,因为就比如num【4】的值并不加和在num【6】里,其实没必要了,因为树状数组用到的操作就是求和和求最大最小值,然后求和的话并不是直接用这些数组元素,而是一个模板函数去求,这个函数求出来的就是1~i的加和,然后求某一个区间的话就是相减,没有任何问题,而且对于树状数组维护的东西又有了较为深刻的认识(可以把其他的值一转化来维护);

//以后的话可以将某些对象抽象,从抽象层面考虑问题,也许问题会变得更容易想,这就是教主说的改变思维方式吧,走出思维的舒适区;

//我还发现对于一个对象在一个程序中,可以分别赋予多种抽象,前提是一个用完之后再用另一个不能混着来;

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm> using namespace std; typedef long long ll; const int maxn = +;
int max_[maxn],min_[maxn],hmin_[maxn],hmax_[maxn];
int num[maxn],a[maxn],b[maxn],sum[maxn];
ll res;
int n,m; int lowbit(int x)
{
return x&(-x);
} void add(int x)
{
while(x<=m)
{
num[x]++;
x+=lowbit(x);
}
} int query(int x)
{
int ans=;
while(x>=)
{
ans+=num[x];
x-=lowbit(x);
}
return ans;
} int main()
{
while(scanf("%d",&n)==)
{
for(int i=;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
sort(b+,b+n+);
m=unique(b+,b+n+)-(b+);
for(int i=;i<=n;i++) a[i]=lower_bound(b+,b+m+,a[i])-b;
memset(num,,sizeof(num));
memset(sum,,sizeof(sum));
for(int i=;i<=n;i++)
{
min_[i]=query(a[i]-);
max_[i]=query(m)-query(a[i]);
sum[i]=sum[i-]+min_[i];
add(a[i]);
}
memset(num,,sizeof(num));
for(int i=n;i>=;i--)
{
hmin_[i]=query(a[i]-);
hmax_[i]=query(m)-query(a[i]);
add(a[i]);
}
res=;
ll num1,num2;
for(int i=;i<=n;i++)
{
num1=max_[i];
num2=sum[n];
res+=num1*num2;
}
//a=c&&b!=d;
for(int i=;i<=n;i++)
{
num1=hmin_[i];
num2=hmax_[i];
res-=num1*num2;
}
//a!=c&&b=d;
for(int i=;i<=n;i++)
{
num1=min_[i];
num2=max_[i];
res-=num1*num2;
}
//a=d&&b!=c;
for(int i=;i<=n;i++)
{
num1=max_[i];
num2=hmax_[i];
res-=num1*num2;
}
//a!=d&&b=c;
for(int i=;i<=n;i++)
{
num1=hmin_[i];
num2=min_[i];
res-=num1*num2;
}
printf("%I64d\n",res);
}
return ;
}

hdu 5792 树状数组+离散化+思维的更多相关文章

  1. hdu 5792(树状数组,容斥) World is Exploding

    hdu 5792 要找的无非就是一个上升的仅有两个的序列和一个下降的仅有两个的序列,按照容斥的思想,肯定就是所有的上升的乘以所有的下降的,然后再减去重复的情况. 先用树状数组求出lx[i](在第 i ...

  2. HDU 1394 树状数组+离散化求逆序数

    对于求逆序数问题,学会去利用树状数组进行转换求解方式,是很必要的. 一般来说我们求解逆序数,是在给定一串序列里,用循环的方式找到每一个数之前有多少个比它大的数,算法的时间复杂度为o(n2). 那么我们 ...

  3. [hdu 4417]树状数组+离散化+离线处理

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4417 把数字离散化,一个查询拆成两个查询,每次查询一个前缀的和.主要问题是这个数组是静态的,如果带修改 ...

  4. Disharmony Trees HDU - 3015 树状数组+离散化

    #include<cstdio> #include<cstring> #include<algorithm> #define ll long long using ...

  5. hdu 4325 树状数组+离散化

    思路:这题的思路很容易想到,把所有时间点离散化,然后按时间一步一步来,当到达时间i的时候处理所有在i处的查询. 这个代码怎一个挫字了得 #include<iostream> #includ ...

  6. Swaps and Inversions HDU - 6318 树状数组+离散化

    #include<iostream> #include<algorithm> #include<cstring> #include<cstdio> us ...

  7. C - The Battle of Chibi HDU - 5542 (树状数组+离散化)

    Cao Cao made up a big army and was going to invade the whole South China. Yu Zhou was worried about ...

  8. hdu 4638 树状数组 区间内连续区间的个数(尽可能长)

    Group Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Subm ...

  9. hdu 4777 树状数组+合数分解

    Rabbit Kingdom Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

随机推荐

  1. [css]等高列的简单实现

    又碰到css等高布局的问题,发现以前没有总结,这里再把基本原理写一下吧. 1.负边距控制法. <div id="content"> <div class=&quo ...

  2. MTD系统架构和yaffs2使用、Nandflash驱动设计

    一.MTD系统架构 1.MTD设备体验 FLASH在嵌入式系统中是必不可少的,它是bootloader.linux内核和文件系统的最佳载体. 在Linux内核中引入了MTD子系统为NORFLASH和N ...

  3. Network基础(六):telnet远程管理

    一.telnet远程管理 目标: 在企业中为方便网络管理员对Cisco设备的配置,一般需事先在Cisco交换机及路由器上开启远程管理的服务,借助网络通过telnet方式远程访问. 方案: 网络管理员通 ...

  4. svn服务端安装、迁移教程、Eclipse切换svn连接库

    svn服务端安装.迁移教程.Eclipse切换svn连接库 安装教程 1.下载svn服务端安装程序 2.运行程序,安装 这里端口号根据自己定义,避免与其他程序冲突 到这里就安装完成 迁移教程 这里举例 ...

  5. vue2 的 过渡(动画)效果

    1.在过渡 效果的使用中 ,key属性需要注意 : 有相同父元素的子元素必须有独特的 key.重复的 key 会造成渲染错误.       参考官方说明:  https://cn.vuejs.org/ ...

  6. ARM系列处理器的分类

    1.ARM ARM即以英国ARM(Advanced RISC Machines)公司的内核芯片作为CPU,同时附加其他外围功能的嵌入式开发板,用以评估内核芯片的功能和研发各科技类企业的产品. ARM ...

  7. 7-4 IP思考

    内网ip和公网Ip 什么是内网IP:  一些小型企业或者学校,通常都是申请一个固定的IP地址,然后通过IP共享(IP Sharing),使用整个公司或学校的机器都能够访问互联网.而这些企业或学校的机器 ...

  8. Could not open lock file/var/lib/dpkg/lock的解决

    Could not open lock file/var/lib/dpkg/lock的解决 在ubuntu系统中利用apt-get install something的时候,有时候会出现无法获得锁的权 ...

  9. webstorm 分屏

  10. webstorm 去点右边白线

    file>settings>editor>general>appearance>show right margin(configured in code style oo ...