Tiny Counting
样例一
- 输入
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的更多相关文章
- 【JZOJ6342】Tiny Counting
description analysis 首先不管\(a,b,c,d\)重复的情况方案数是正逆序对之积 如果考虑\(a,b,c,d\)有重复,只有四种情况,下面括号括起来表示该位置重复 比如\(\{a ...
- [考试反思]1114csp-s模拟测试115:零迟
最后一次了,允许自己混进榜里吧. 没有心态,原题不会做(真的忘了) T2的搜索没有分. 「 零 · 迟 」:酷刑 只有在最后的时刻才开始意识到,一切的一切都已经晚了. 就在眼前了.没有机会了. 退役, ...
- .NET平台开源项目速览(14)最快的对象映射组件Tiny Mapper
好久没有写文章,工作甚忙,但每日还是关注.NET领域的开源项目.五一休息,放松了一下之后,今天就给大家介绍一个轻量级的对象映射工具Tiny Mapper:号称是.NET平台最快的对象映射组件.那就一起 ...
- 萌新笔记——Cardinality Estimation算法学习(二)(Linear Counting算法、最大似然估计(MLE))
在上篇,我了解了基数的基本概念,现在进入Linear Counting算法的学习. 理解颇浅,还请大神指点! http://blog.codinglabs.org/articles/algorithm ...
- POJ_2386 Lake Counting (dfs 错了一个负号找了一上午)
来之不易的2017第一发ac http://poj.org/problem?id=2386 Lake Counting Time Limit: 1000MS Memory Limit: 65536 ...
- ZOJ3944 People Counting ZOJ3939 The Lucky Week (模拟)
ZOJ3944 People Counting ZOJ3939 The Lucky Week 1.PeopleConting 题意:照片上有很多个人,用矩阵里的字符表示.一个人如下: .O. /|\ ...
- Tiny Mapper
今天看到一个对象映射工具-TinyMapper 1.介绍 Tiny Mapper是一个.net平台的开源的对象映射组件,其它的对象映射组件比如AutoMapper有兴趣的可以去看,Tiny Mappe ...
- 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 ...
- 1004. Counting Leaves (30)
1004. Counting Leaves (30) A family hierarchy is usually presented by a pedigree tree. Your job is ...
随机推荐
- 微服务示例-Spring Cloud
1~开发准备 JDK:1.8 Spring Boot:1.5.9.RELEASE Spring Coud:Edgware.RELEASE IDE:IntelliJ IDEA 2017 Maven:3. ...
- Windows Vista 的历史地位
Windows Vista,这是一个不那么如雷贯耳的Windows名字,很多人甚至从来没有体验过这个操作系统.但是,Windows Vista刚刚推出时候所引起的话题性,恐怕是其后的Win7也难以与之 ...
- Bamboo 0.2.11 发布,HAProxy 自动配置
Bamboo 0.2.11 发布,此版本更新内容如下: 新特性 提供更多的模板字符串函数:strings.Split, strings.Join,strings.Replace, strings.T ...
- Delphi线程类 DIY(把类指针作为参数传进去,就可以执行类里面的方法啦)
Delphi 封装了一个很强大的线程类 TThread, 我们也自己动手制作一个简单的线程类 首先Type一个类 type TwwThread = class constructor Create; ...
- DUI-模态对话框的实现
模态对话框要求自己实现自己的消息循环,当然,建议它还是处于主线程中,所以最好是由它再调用主线程的消息循环函数,此时主线程自身的消息循环函数被阻塞,等待模板对话框的消息循环函数退出 参考代码如下: 1 ...
- 你真的懂printf么?
自从你进入程序员的世界,就开始照着书本编写着各种helloworld,大笔一挥: printf("Hello World!\n"); 于是控制台神奇地出现了一行字符串,计算机一句温 ...
- spring boot单元测试之RestTemplate(三)——api详解
本篇内容来自翟永超的<Springcloud微服务实战>,转载请注明. 一.GET请求 在RestTemplate中,对GET请求可以通过如下两个方法进行调用实现. 第一种:getForE ...
- HTML连载12-体验CSS
一.通过标签来修改标签有哪些缺点: (1)需要记忆那些标签有哪些属性 (2)若该标签没有这个属性,则修改失败 (3)需求变更,需要修改大量的代码 (4)HTML标签及用于添加语义,与我们的定义不相符 ...
- Azkaban学习之路(四)—— Azkaban Flow 2.0的使用
一.Flow 2.0 简介 1.1 Flow 2.0 的产生 Azkaban 目前同时支持 Flow 1.0 和 Flow2.0 ,但是官方文档上更推荐使用Flow 2.0,因为Flow 1.0会在将 ...
- spring cloud 系列第2篇 —— eureka 高可用注册中心的搭建 (F版本)
源码仓库地址:https://github.com/heibaiying/spring-samples-for-all 一.项目结构 eureka-server为服务注册中心,负责服务的管理: eur ...
