也许更好的阅读体验

样例一

  • 输入

    4

    1 4 3 2
  • 输出

    3

样例二

  • 输入

    5

    9 1 0 0 5
  • 输出

    8

题解

这是本人自己想了2个半小时才想出来的方法,稍稍有点复杂但是很好理解

题目的意思就是给定一个数组,求有多少个数字不同的顺序对和逆序对(Sa<Sb,Sc>Sd)

那么总方案数应该就是 顺序对数×与之对应合法的逆序对数

当然这些是不可以直接算出来的

sx[a] 表示a与后面的数组成的顺序对个数(a,x)

nx[a] 表示a与后面的树组成的逆序对个数

asnx[a] 表示a作为前面多少个数的逆序对(x,a)

sxc[a] 表示a的所有顺序对的作为逆序对个数的和

sxnx[a] 表示a的顺序对的逆序对个数

sum_nx 所有的逆序对总数

暂时没理解没关系,后面会解释清楚

考虑先枚举一个a,那么我们要做的就是找到剩下的b,c,d了

现在有这样的一个公式\(sx[a]*sum_nx\)即将a组成的顺序对与所有的逆序对组合,显然这是错误的,我们考虑将其变得正确

考虑最简单的,先去除a=c的情况

对于这种情况,因为我们把a的顺序对与所有逆序对组合了,现在不能要a开头的逆序对,我们只需 把a的逆序对个数减去 即可

即\(sx[a]*(sum_nx-nx[a])\)

再考虑去除a=d的情况

对于这种情况,我们只需 把a作为前面的逆序对的个数减去 即可

即\(sx[a]*(sum_nx-nx[a]-asnx[a])\)

再去除b=c的情况

实际上,我们也只需要 把b的逆序对个数减去 即可

即\(sx[a]*(sum_nx-nx[a]-asnx[a]-nx[b])\)

但是上面的b对于不同a的顺序对这样我们又得枚举b,复杂度就降低很多

我们把上面的式子好好想一下,所有的b都会被算且只会被算一次那么其实我们是可以用树状数组提前维护好的

即维护a的所有顺序对的逆序对的个数

式子就变成\(sx[a]*(sum_nx-nx[a]-asnx[a])-sxnx[a])\)

最后还剩b=d的情况

对于a所有的顺序对,都有机会作为b,这时以它为d的都不行了

所以要减去顺序对的作为逆序对的个数即减去sxc[a]

即\(sx[a]*(sum_nx-nx[a]-asnx[a])-sxnx[a]-sxc[a]\)

所有的情况都讨论完了,最终的答案就是枚举所有的a

再\(ans+=sx[a]*(sum_nx-nx[a]-asnx[a])-sxnx[a]-sxc[a]\)

代码

由于不开long long博主只得了70分,所以后来就加了一堆long long,复杂度是肯定没有问题的

/*******************************
Author:Morning_Glory
LANG:C++
Created Time:2019年05月11日 星期六 08时10分14秒
*******************************/
#include <cstdio>
#include <fstream>
#include <algorithm>
#define rint register int
#define num(x) s[x].num
#define id(x) s[x].id
#define sx(x) s[x].sx
#define nx(x) s[x].nx
#define asnx(x) s[x].asnx
#define sxc(x) s[x].sxc
#define sxnx(x) s[x].sxnx
#define nxsx(x) s[x].nxsx
#define ll long long
using namespace std;
const int maxn = 100005;
struct Number{
ll id,num,sx,nx,asnx,sxc,sxnx;
}s[maxn];
int n,cnt;
ll ans,sum_nx;
ll c[5][maxn];//0 逆序 1 顺序 2 作为逆序 3 顺序的作为逆序 4 顺序的逆序
//{{{cin 读入优化
struct IO{
template<typename T>
IO & operator>>(T&res){
res=0;
bool flag=false;
char ch;
while((ch=getchar())>'9'||ch<'0') flag|=ch=='-';
while(ch>='0'&&ch<='9') res=(res<<1)+(res<<3)+(ch^'0'),ch=getchar();
if (flag) res=~res+1;
return *this;
}
}cin;
//}}}
//排序用于离散化
inline bool comp (Number x,Number y) { return x.id<y.id; }//按输入顺序排序
inline bool com (Number x,Number y){ return x.num<y.num; }//按数值大小排序
inline int lowbit (int x){ return x & -x; }
//{{{insert(l,r,v,x)树状数组的插入
void insert (int l,int r,ll v,int x) {
for (ll i=l;i<=n;i+=lowbit(i)) c[x][i]+=v;
for (ll i=r+1;i<=n;i+=lowbit(i)) c[x][i]-=v;
}
//}}}
//{{{query(l,x)树状数组的查询
ll query (int l,int x) {
ll res=0;
for (ll i=l;i>=1;i-=lowbit(i)) res+=c[x][i];
return res;
}
//}}}
//{{{pre 将数据离散化
void pre ()
{
sort(s+1,s+n+1,com);
for (rint i=1;i<=n;++i){
bool flag=num(i)==num(i+1);
num(i)=++cnt;
cnt-=flag;
}
sort(s+1,s+n+1,comp);
}
//}}}
//{{{deal
void deal ()//维护出每个位置的,顺序,逆序等等
{
//0 逆序 1 顺序 2 作为逆序 3 顺序的作为逆序 4 顺序的逆序
for (rint i=1;i<=n;++i){
insert(1,num(i)-1,1,2);
asnx(i)=query(num(i),2);
}
for (rint i=n;i>=1;--i){
nx(i)=query(num(i),0);//逆序
sx(i)=query(num(i),1);//顺序
sxc(i)=query(num(i),3);//顺序的作为逆序 insert(num(i)+1,n,1,0);//逆序
insert(1,num(i)-1,1,1);//顺序
insert(1,num(i)-1,asnx(i),3);//顺序的作为逆序 sum_nx+=nx(i);//总逆序
}
for (rint i=n;i>=1;--i){
sxnx(i)=query(num(i),4);//顺序的逆序个数
insert(1,num(i)-1,nx(i),4);//同上
}
}
//}}}
int main()
{
cin>>n;
for (rint i=1;i<=n;++i)
cin>>num(i),id(i)=i; pre();//离散化
deal();//预处理 for (rint a=1;a<=n;++a)
ans+=1ll*sx(a)*(sum_nx-nx(a)-asnx(a))-sxnx(a)-sxc(a); printf("%lld\n",ans);
return 0;
}

如以上没有看懂请指出问题,博主会加以修改,谢谢

Tiny Counting的更多相关文章

  1. 【JZOJ6342】Tiny Counting

    description analysis 首先不管\(a,b,c,d\)重复的情况方案数是正逆序对之积 如果考虑\(a,b,c,d\)有重复,只有四种情况,下面括号括起来表示该位置重复 比如\(\{a ...

  2. [考试反思]1114csp-s模拟测试115:零迟

    最后一次了,允许自己混进榜里吧. 没有心态,原题不会做(真的忘了) T2的搜索没有分. 「 零 · 迟 」:酷刑 只有在最后的时刻才开始意识到,一切的一切都已经晚了. 就在眼前了.没有机会了. 退役, ...

  3. .NET平台开源项目速览(14)最快的对象映射组件Tiny Mapper

    好久没有写文章,工作甚忙,但每日还是关注.NET领域的开源项目.五一休息,放松了一下之后,今天就给大家介绍一个轻量级的对象映射工具Tiny Mapper:号称是.NET平台最快的对象映射组件.那就一起 ...

  4. 萌新笔记——Cardinality Estimation算法学习(二)(Linear Counting算法、最大似然估计(MLE))

    在上篇,我了解了基数的基本概念,现在进入Linear Counting算法的学习. 理解颇浅,还请大神指点! http://blog.codinglabs.org/articles/algorithm ...

  5. POJ_2386 Lake Counting (dfs 错了一个负号找了一上午)

    来之不易的2017第一发ac http://poj.org/problem?id=2386 Lake Counting Time Limit: 1000MS   Memory Limit: 65536 ...

  6. ZOJ3944 People Counting ZOJ3939 The Lucky Week (模拟)

    ZOJ3944 People Counting ZOJ3939 The Lucky Week 1.PeopleConting 题意:照片上有很多个人,用矩阵里的字符表示.一个人如下: .O. /|\ ...

  7. Tiny Mapper

    今天看到一个对象映射工具-TinyMapper 1.介绍 Tiny Mapper是一个.net平台的开源的对象映射组件,其它的对象映射组件比如AutoMapper有兴趣的可以去看,Tiny Mappe ...

  8. find out the neighbouring max D_value by counting sort in stack

    #include <stdio.h> #include <malloc.h> #define MAX_STACK 10 ; // define the node of stac ...

  9. 1004. Counting Leaves (30)

    1004. Counting Leaves (30)   A family hierarchy is usually presented by a pedigree tree. Your job is ...

随机推荐

  1. CS224n笔记一:开端

    何为自然语言处理 自然语言处理的目标是让计算机处理或者"理解"自然语言,以完成有意义的任务,如QA等. 自然语言处理涉及的层次 输入有两个来源:语音和文本,所以第一级是语音识别,O ...

  2. file.delete()与file.deleteOnExit(); 的区别

    file.delete()   //删除文件,删除的是创建File对象时指定与之关联创建的那个文件.这是一个立刻执行的操作 file.deleteOnExit();   //在JVM进程退出的时候删除 ...

  3. WebRequest请求错误(服务器提交了协议冲突. Section=ResponseHeader Detail=CR 后面必须是 LF)

    WebRequest请求错误(服务器提交了协议冲突. Section=ResponseHeader Detail=CR 后面必须是 LF)解决办法,天津config文件,增加一个配置如下 <?x ...

  4. Windows下搭建go语言开发环境 以及 开发IDE (附下载链接)

    1.下载 并且 安装 Go安装包   =========================================================== 在CSDN上传了我的版本,供大家下载: = ...

  5. Java集合 ArrayList原理及使用

    ArrayList是集合的一种实现,实现了接口List,List接口继承了Collection接口.Collection是所有集合类的父类.ArrayList使用非常广泛,不论是数据库表查询,exce ...

  6. .NET程序员如何快入门Spring Boot

    本篇文章将教你作为一个.NET程序员如何快入门Spring Boot.你不需要用Eclipse,也不需要用IDEA.已经习惯了VS,其他的IDE-- 但不得不说VS Code很厉害,一用就喜欢.微软给 ...

  7. Python基础,day2

    程序练习 程序:购物车程序 需求: 启动程序后,让用户输入工资,然后打印商品列表 允许用户根据商品编号购买商品 用户选择商品后,检测余额是否够,够就直接扣款,不够就提醒 可随时退出,退出时,打印已购买 ...

  8. Liferay6.1 配置友好的URL映射

    说明:以下内容和官方文档相差不大,如果您英文较好,建议直接去读官方文档,地址是:https://dev.liferay.com/develop/tutorials/-/knowledge_base/6 ...

  9. 04-MySQL中的数据类型

    1 整体说明MYsql的数据类型#1. 数字:    整型:tinyint  int  bigint    小数:        float :在位数比较短的情况下不精准        double ...

  10. 【MySQL插入更新重复值】ON DUPLICATE KEY UPDATE用法

    要插入的数据  与表中记录数据的 惟一索引或主键中产生重复值,那么就会发生旧行的更新 弊端:造成主键自增不连续.适合数据量不大的表. ON DUPLICATE KEY UPDATE后面的条件 eg有如 ...