正题

题目链接:http://www.ybtoj.com.cn/contest/123/problem/1


题目大意

给出\(3\)个长度为\(n\)的排列\(A,B,C\)。然后一个下标集合\(S\)的三元组是

\[(max\{A_i\},max\{B_i\},max\{C_i\})(i\in S)
\]

求所有下标集合不同的三元组数量

\(1\leq n\leq 10^5\)


解题思路

所有下标集合的三元组都能用一个\(|S|\leq 3\)的集合代替,所以我们只考虑\(|S|\leq 3\)的就好了。

\(|S|=1\)的个数就是\(n\),直接累加即可。

\(|S|=2\)的话,那就代表某个下标霸占了两个最大值,而另一个一定是另一个下标的,如果是\(a,b\)最大,那么我们就要找满足\(a_i> a_j,b_i> a_j,c_i< c_j\)的方案,用三维偏序就好了。

然后\(a,c\)和\(b,c\)的情况也都要做

\(|S|=3\)的话很麻烦,考虑容斥,总方案\(\binom n 3\)减去有一个下标是至少两个的最大值。

同样和上面,先考虑\(a,b\),假设下标\(i\)满足\(a_i>a_j,b_i>b_j\)的情况有\(k\)种,那么就好有\(\binom{k}{2}\)种情况使得\(i\)占据了至少两个最大值。

同理\(a,c\)和\(b,c\)也要做,这是二维偏序,直接树状数组就好了。

但是发现对于\(i\)占据了三个最大值的情况我们统计了三次,需要加回多余的两次,那么统计\(a_i>a_j,b_i>b_j,c_i>c_j\)的个数\(k\),然后加回\(k(k-1)\)的方案就好了,这个也要三维偏序

代码里三维偏序用的是\(CDQ\)分治+树状数组

时间复杂度\(O(n\log^2 n)\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define lowbit(x) (x&-x)
using namespace std;
const ll N=1e5+10;
struct node{
ll a,b,c;
}w[N],a[N],b[N];
ll n,ans,sum,t[N],g[N];
void Change(ll x,ll val){
while(x<=n){
t[x]+=val;
x+=lowbit(x);
}
return;
}
ll Ask(ll x){
ll ans=0;
while(x){
ans+=t[x];
x-=lowbit(x);
}
return ans;
}
void Merge(ll l,ll mid,ll r){
ll p=l,q=mid+1;
for(ll i=1;i<=r-l+1;i++){
if(p<=mid&&w[p].b<=w[q].b||q>r)b[i]=w[p],p++;
else b[i]=w[q],q++;
}
for(ll i=1;i<=r-l+1;i++)w[l+i-1]=b[i];
return;
}
void CDQ(ll l,ll r,bool op){
if(l==r)return;
ll mid=(l+r)>>1;
CDQ(l,mid,op);CDQ(mid+1,r,op);
ll p=l,tmp;
for(ll i=mid+1;i<=r;i++){
while(p<=mid&&w[p].b<w[i].b)
Change(w[p].c,1),p++;
sum+=(tmp=Ask(w[i].c));
g[w[i].a]+=(op?tmp:0);
}
for(ll i=l;i<p;i++)Change(w[i].c,-1);
Merge(l,mid,r);return;
}
bool cmp(node x,node y)
{return x.a<y.a;}
void solve(){
sort(w+1,w+1+n,cmp);
for(ll i=1;i<=n;i++){
ll tmp=Ask(w[i].b);
ans-=tmp*(tmp-1)/2;
Change(w[i].b,1);
}
memset(t,0,sizeof(t));
return;
}
signed main()
{
freopen("subset.in","r",stdin);
freopen("subset.out","w",stdout);
scanf("%lld",&n);ans=n;
for(ll i=1;i<=n;i++)scanf("%lld",&a[i].a);
for(ll i=1;i<=n;i++)scanf("%lld",&a[i].b);
for(ll i=1;i<=n;i++)scanf("%lld",&a[i].c); for(ll i=1;i<=n;i++)
w[i].a=a[i].a,w[i].b=a[i].b,w[i].c=n-a[i].c+1;
sort(w+1,w+1+n,cmp);CDQ(1,n,0);
for(ll i=1;i<=n;i++)
w[i].a=a[i].a,w[i].b=a[i].c,w[i].c=n-a[i].b+1;
sort(w+1,w+1+n,cmp);CDQ(1,n,0);
for(ll i=1;i<=n;i++)
w[i].a=a[i].b,w[i].b=a[i].c,w[i].c=n-a[i].a+1;
sort(w+1,w+1+n,cmp);CDQ(1,n,0);
ans+=sum;ans+=n*(n-1)*(n-2)/6; for(ll i=1;i<=n;i++)w[i].a=a[i].a,w[i].b=a[i].b;solve();
for(ll i=1;i<=n;i++)w[i].a=a[i].b,w[i].b=a[i].c;solve();
for(ll i=1;i<=n;i++)w[i].a=a[i].a,w[i].b=a[i].c;solve(); for(ll i=1;i<=n;i++)
w[i].a=a[i].a,w[i].b=a[i].b,w[i].c=a[i].c;
sort(w+1,w+1+n,cmp);
CDQ(1,n,1);
for(ll i=1;i<=n;i++)ans+=g[i]*(g[i]-1);
printf("%lld\n",ans);
}

YbtOJ#791-子集最值【三维偏序】的更多相关文章

  1. NEUOJ 1702 撩妹全靠魅力值 (三维偏序)

    题目链接:http://acm.neu.edu.cn/hustoj/problem.php?id=1702 题目大意:就是问每个人三个属性同时不低于另外几个人....人不分先后 经典的三维偏序问题 解 ...

  2. NEUOJ 1702:撩妹全靠魅力值(CDQ分治三维偏序)

    http://acm.neu.edu.cn/hustoj/problem.php?id=1702 思路:三维偏序模板题,用CDQ分治+树状数组或者树套树.对于三元组(x,y,z),先对x进行排序,然后 ...

  3. BZOJ 3262: 陌上花开 [CDQ分治 三维偏序]

    Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当 ...

  4. cdq分治解决三维偏序

    问题背景 在三维坐标系中有n个点,坐标为(xi,yi,zi). 定义一个点A比一个点B小,当且仅当xA<=xB,yA<=yB,zA<=zB.问对于每个点,有多少个点比它小.(n< ...

  5. P3810 【模板】三维偏序(陌上花开)

    P3810 [模板]三维偏序(陌上花开) cdq分治+树状数组 三维偏序模板题 前两维用cdq分治,第三维用树状数组进行维护 就像用树状数组搞逆序对那样做--->存权值的出现次数 attenti ...

  6. Luogu 3810 & BZOJ 3262 陌上花开/三维偏序 | CDQ分治

    Luogu 3810 & BZOJ 3263 陌上花开/三维偏序 | CDQ分治 题面 \(n\)个元素,每个元素有三个值:\(a_i\), \(b_i\) 和 \(c_i\).定义一个元素的 ...

  7. 【算法学习】【洛谷】cdq分治 & P3810 三维偏序

    cdq是何许人也?请参看这篇:https://wenku.baidu.com/view/3b913556fd0a79563d1e7245.html. 在这篇论文中,cdq提出了对修改/询问型问题(Mo ...

  8. HDU 5517 【二维树状数组///三维偏序问题】

    题目链接:[http://acm.split.hdu.edu.cn/showproblem.php?pid=5517] 题意:定义multi_set A<a , d>,B<c , d ...

  9. BZOJ3262:陌上花开 & 洛谷3810:三维偏序——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=3262 https://www.luogu.org/problemnew/show/3810 Desc ...

随机推荐

  1. "image watch" for QtCreator

    Image Watch Image Watch 是Visual Studio的一个插件,用来在C++ 调试时显示内存中的位图图像.可以直观的看到图像的变化而不用添加额外的显示代码.其内建了对OpenC ...

  2. 让div占据父元素剩下的所有位置

    场景模拟: 现在有一个父容器,里面有俩个div,左边的要给一个固定的200px的宽度,父容器剩下的宽度都归右边的div该怎么完成?HTML代码: <div class="wrap&qu ...

  3. Quartz任务调度(5)TriggerListener分版本超详细解析

    TriggerListener 在我们的触发器监听器中,也包含了一系列监听方法 方法 说明 getName() 定义并返回监听器的名字 triggerFired() 当与监听器相关联的 Trigger ...

  4. Promise.all()

    语法:Promise.all(iterable); 参数:iterable 一个可迭代对象,如 Array 或 String. 返回值:如果传入的参数是一个空的可迭代对象,则返回一个已完成(alrea ...

  5. SSD算法原理

    Paper: https://arxiv.org/pdf/1512.02325.pdf SSD用神经网络(VGG)提取多层feature map ,来实现对不同大小物体的检测.如下图所示: We us ...

  6. 三.Go微服务--令牌桶实现原理

    1. 前言 在上一篇文章 Go微服务: 令牌桶 当中简单的介绍了令牌桶实现的原理,然后利用 /x/time/rate 这个库 10 行代码写了一个基于 ip 的 gin 限流中间件,那这个功能是怎么实 ...

  7. HCNP Routing&Switching之OSPF LSA类型(二)

    前文我们了解了OSPF的一类.二类.三类LSA,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15209829.html:今天我们来聊一聊OSPF的四类和五类L ...

  8. MySQL版本浅介

    一.关于MySQL发行版介绍: 1. MySQL官方发行版 MySQL是最流行的数据库,主要特点: 简单:MySQL使用很简单,可以无师自通地参照文档安装运行和使用MySQL,几乎没有什么门槛. 开源 ...

  9. 复习&反思

    阴间题目 半夜 糖果 Cicada 与排序 排列 Cover 玩具 夜莺与玫瑰 God Knows 简单的填数 反思 20210826 Lighthouse,Miner,Lyk Love painti ...

  10. Git 系列教程(6)- 查看 commit 提交历史

    查看提交历史 在提交了若干更新,又或者克隆了某个项目之后,如何查看提交历史 git log 官方栗子 运行下面的命令获取该项目: git clone https://github.com/scha 运 ...