也许更好的阅读体验

样例一

  • 输入

    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. VS2013设置release版本可调试

    http://blog.csdn.net/caoshangpa/article/details/76575640

  2. 大数据基础之Kafka(1)简介、安装及使用

    kafka2.0 http://kafka.apache.org 一 简介 Kafka® is used for building real-time data pipelines and strea ...

  3. 第四章 自定义sol合约转化java代码,并实现调用

     鉴于笔者以前各大博客教程都有很多人提问,早期建立一个技术交流群,里面技术体系可能比较杂,想了解相关区块链开发,技术提问,请加QQ群:538327407 准备工作 1.官方参考说明文档 https:/ ...

  4. SYN5006型电机同步编码脉冲分配器

    SYN5006型电机同步编码脉冲分配器 编码器信号分配板增量式编码器脉冲分配器使用说明视频链接: http://www.syn029.com/h-pd-81-0_310_13_-1.html 请将此链 ...

  5. 再说Java集合,subList之于ArrayList

    上一章说了很多ArrayList相关的内容,但还有一块儿内容没说到,那就是subList方法.先看一段代码 public static void testSubList() { List<Str ...

  6. 用nodejs调用webservice

    用nodejs调用webservice,是用soap包实现的. 步骤如下: 第一步:安装soap包 npm  install soap 第二部:调用webservice var soap = requ ...

  7. jmeter模拟spike测试(尖峰测试)

    概述 尖峰测试(Spike testing)在性能测试中属于压力测试的一个子集.指的是在某一瞬间或者多个频次下用户数和压力陡然增加的场景. 为了验证我们的网站在访问用户急剧增加的情况下,或者短时间内反 ...

  8. java模拟键鼠操作

    很久之前百度的,所以忘记了作者,所以仅作为自己的日记纪录在此: package com.robot.test;import java.awt.AWTException;import java.awt. ...

  9. FPM

    https://github.com/pangudashu/php7-internal/blob/master/1/fpm.md

  10. SQL经典练习题50--mysql

    --1.学生表 Student(Sid,Sname,Sage,Ssex)? --Sid 学生编号,Sname 学生姓名,Sage 出生年月,Ssex 学生性别 --2.课程表? Course(Cid, ...