【题意】

给定一个有n个元素的序列,元素编号为1~n,每个元素有三个属性a,b,c,求序列中满足i<j且ai<aj且bi<bj且ci<cj的数对(i,j)的个数。

对于30%的数据,n<=5000。

对于100%的数据,1<=n<=50000(原题写错了哈哈),保证所有的ai、bi、ci分别组成三个1~n的排列。

【解法】

标题已经说了这是偏序,读完题,这就是个四维偏序模板题(位置一维,a,b,c剩下三维)。

解法多多,我用的是CDQ树套树(树套树写的树状数组套替罪羊树,毕竟在我的印象里替罪羊树在随机数据下跑得飞快)。

第一维已经有序,不用我们预处理,这样就可以按第一维(位置)分治,再把第二维(a)排序,剩下的第三维(b)和第四维(c)直接树套树就可以了(我用的是第三维树状数组,第四维平衡树)。

当然写CDQ套CDQ+树状数组应该也可以,然而本鶸渣不会写……

也可以写树套树套树……然而怎么写……

贴个代码:

 #include<cstdio>
#include<cstring>
#include<algorithm>
#define siz(x) ((x)?((x)->size):(0))
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int maxn=;
const double A=0.65;
struct node{//Scapegoat Tree
int data,size;
node *lc,*rc,*prt;
node(int d=):data(d),size(),lc(NULL),rc(NULL),prt(NULL){}
inline void refresh(){size=siz(lc)+siz(rc)+;}
}*root[maxn];
struct B{
int id,a,b,c;
bool operator<(const B &a)const{return this->a<a.a;}
}a[maxn],b[maxn];
void CDQ(int,int);
void add(int,int);
void del(int,int);
int query(int,int);
void insert(int);
void erase(int);
int rank(int);
node *insert(node*);
node *find(int);
node *erase(node*);
node *findmax(node*);
void rebuild(node*);
void zorder(node*);
void removetree(node*);
node *rebuild(int,int);
int n,T,cnt,data[maxn];
long long ans=0ll;
int main(){
#define MINE
#ifdef MINE
freopen("partial_order.in","r",stdin);
freopen("partial_order.out","w",stdout);
#endif
scanf("%d",&n);
for(int i=;i<=n;i++)a[i].id=i;
for(int i=;i<=n;i++)scanf("%d",&a[i].a);
for(int i=;i<=n;i++)scanf("%d",&a[i].b);
for(int i=;i<=n;i++)scanf("%d",&a[i].c);
CDQ(,n);
printf("%lld",ans);
#ifndef MINE
printf("\n-------------------------DONE-------------------------\n");
for(;;);
#endif
return ;
}
void CDQ(int l,int r){
if(l>=r)return;
int mid=(l+r)>>;
CDQ(l,mid);
CDQ(mid+,r);
int i=l,j=mid+,k=l;
while(i<=mid&&j<=r){
if(a[i]<a[j])b[k++]=a[i++];
else b[k++]=a[j++];
}
while(i<=mid)b[k++]=a[i++];
while(j<=r)b[k++]=a[j++];
for(int i=l;i<=r;i++){
a[i]=b[i];
if(a[i].id<=mid)add(a[i].b,a[i].c);
else ans+=query(a[i].b,a[i].c);
}
for(int i=l;i<=r;i++)if(a[i].id<=mid)del(a[i].b,a[i].c);
}
void add(int x,int d){
while(x<=n){
T=x;
insert(d);
x+=lowbit(x);
}
}
void del(int x,int d){
while(x<=n){
T=x;
erase(d);
x+=lowbit(x);
}
}
int query(int x,int d){
int ans=;
while(x){
T=x;
ans+=rank(d);
x-=lowbit(x);
}
return ans;
}
void insert(int x){
node *rt=insert(new node(x));
if(rt)rebuild(rt);
}
void erase(int x){
node *rt=erase(find(x));
if(rt)rebuild(rt);
}
int rank(int x){
node *rt=root[T];
int ans=;
while(rt){
if(x<=rt->data)rt=rt->lc;
else{
ans+=siz(rt->lc)+;
rt=rt->rc;
}
}
return ans;
}
node *insert(node *x){
if(!root[T]){
root[T]=x;
return NULL;
}
node *rt=root[T];
for(;;){
if(x->data<rt->data){
if(rt->lc)rt=rt->lc;
else{
rt->lc=x;
break;
}
}
else{
if(rt->rc)rt=rt->rc;
else{
rt->rc=x;
break;
}
}
}
x->prt=rt;
x=NULL;
for(;rt;rt=rt->prt){
rt->refresh();
if(max(siz(rt->lc),siz(rt->rc))>A*rt->size)x=rt;
}
return x;
}
node *find(int x){
node *rt=root[T];
while(rt){
if(x==rt->data)return rt;
else if(x<rt->data)rt=rt->lc;
else rt=rt->rc;
}
return NULL;
}
node *erase(node *x){
if(x->lc&&x->rc){
node *y=findmax(x->lc);
x->data=y->data;
return erase(y);
}
if(!x->lc&&!x->rc){
if(x->prt){
if(x==x->prt->lc)x->prt->lc=NULL;
else x->prt->rc=NULL;
}
else root[T]=NULL;
}
else if(x->lc&&!x->rc){
x->lc->prt=x->prt;
if(x->prt){
if(x==x->prt->lc)x->prt->lc=x->lc;
else x->prt->rc=x->lc;
}
else root[T]=x->lc;
}
else if(!x->lc&&x->rc){
x->rc->prt=x->prt;
if(x->prt){
if(x==x->prt->lc)x->prt->lc=x->rc;
else x->prt->rc=x->rc;
}
else root[T]=x->rc;
}
node *rt=x->prt;
delete x;
x=NULL;
for(;rt;rt=rt->prt){
rt->refresh();
if(max(siz(rt->lc),siz(rt->rc))>A*rt->size)x=rt;
}
return x;
}
node *findmax(node *x){
while(x->rc)x=x->rc;
return x;
}
void rebuild(node *rt){
cnt=;
zorder(rt);
node *x=rebuild(,cnt);
x->prt=rt->prt;
if(rt->prt){
if(rt==rt->prt->lc)rt->prt->lc=x;
else rt->prt->rc=x;
}
else root[T]=x;
removetree(rt);
}
void removetree(node *x){
if(!x)return;
removetree(x->lc);
removetree(x->rc);
delete x;
}
void zorder(node *x){
if(!x)return;
zorder(x->lc);
data[++cnt]=x->data;
zorder(x->rc);
}
node *rebuild(int l,int r){
if(l>r)return NULL;
int mid=(l+r)>>;
node *x=new node(data[mid]);
x->lc=rebuild(l,mid-);
if(x->lc)x->lc->prt=x;
x->rc=rebuild(mid+,r);
if(x->rc)x->rc->prt=x;
x->refresh();
return x;
}

【后记】

这个题是用CDQ+树状数组水掉三维偏序之后的脑洞的产物……貌似在报复社会……

自己真是玩疯了……

COGS 2479 偏序 题解的更多相关文章

  1. COGS 2479. [HZOI 2016]偏序 [CDQ分治套CDQ分治 四维偏序]

    传送门 给定一个有n个元素的序列,元素编号为1~n,每个元素有三个属性a,b,c,求序列中满足i<j且ai<aj且bi<bj且ci<cj的数对(i,j)的个数. 对于100%的 ...

  2. COGS 2479. [HZOI 2016] 偏序 (CDQ套CDQ)

    传送门 解题思路 四维偏序问题,模仿三维偏序,第一维排序,第二维CDQ,最后剩下二元组,发现没办法处理,就继续嵌套CDQ分治.首先把二元组的左右两边分别打上不同的标记,因为统计答案时只统计左边对右边的 ...

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

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

  4. CDQ分治学习笔记(三维偏序题解)

    首先肯定是要膜拜CDQ大佬的. 题目背景 这是一道模板题 可以使用bitset,CDQ分治,K-DTree等方式解决. 题目描述 有 nn 个元素,第 ii 个元素有 a_iai​.b_ibi​.c_ ...

  5. COGS 2479 奇怪的姿势卡♂过去 (bitset+折半)

    思路: 此题显然是CDQ套CDQ套树套树 (然而我懒) 想用一种奇怪的姿势卡过去 就出现了以下解法 5w*5w/8的bitset hiahiahia 但是空间会爆怎么办啊- 折半~ 变成5w*2.5w ...

  6. CDQ分治嵌套模板:多维偏序问题

    CDQ分治2 CDQ套CDQ:四维偏序问题 题目来源:COGS 2479 偏序 #define LEFT 0 #define RIGHT 1 struct Node{int a,b,c,d,bg;}; ...

  7. 四维偏序 CDQ套CDQ

    对CDQ深一步的理解 昨天做了一道CDQ,看了一堆CDQ可做的题,今天又做了一道四维偏序 感觉对CDQ的理解又深了一点,故来写一写现在自己对于CDQ的理解 CDQ其实就是实现了这样的一个问题的转化: ...

  8. 【教程】CDQ套CDQ——四维偏序问题

    前言 上一篇文章已经介绍了简单的CDQ分治,包括经典的二维偏序和三维偏序问题,还有带修改和查询的二维/三维偏序问题.本文讲介绍多重CDQ分治的嵌套,即多维偏序问题. 四维偏序问题       给定N( ...

  9. 几道很Interesting的偏序问题

    若干道偏序问题(STL,分块) 找了4道题目 BZOJ陌上花开(权限题,提供洛谷链接) Cogs2479偏序 Cogs2580偏序II Cogs2639偏序++ 作为一个正常人,肯定先看三维偏序 做法 ...

随机推荐

  1. hdu 1873 看病要排队(优先级队列)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1873 题目大意: 三个医生看病,病人排队看病,病人有优先级,优先级高的提前看病,同样的优先级按先后.I ...

  2. webapi输入验证过滤器ValidationActionFilter

    public class validationActionFilter:ActionFilterAttribute { public override void OnActionExecuting(S ...

  3. 网络广告术语CPC、CPM和CTR的含义和关系

    1.       CPC(Cost-per-click):对于广告主来说,就是每次点击(广告)的(付给网站主的)成本:对于媒体(或网站主)来说,就是用户每次点击(广告)(向广告主收取)的费用.可以用公 ...

  4. VS2012打包Winform教程 [转]

    VS2012打包部署Winform程序 打包前的准备工作: 里边会提到第一次使用的时候打开网页填数据什么的..最终要下载一个EXE文件..其实大可不必.. 直接百度InstallShield2012S ...

  5. Orchard源码分析(5):Host相关(Orchard.Environment.DefaultOrchardHost类)

    概述 Host 是应用程序域级的单例,代表了Orchard应用程序.其处理应用程序生命周期中的初始化.BeginRequest事件.EndRequest事件等. 可以简单理解为HttpApplicat ...

  6. iOS-设置UIPageControl 显示图片

    UIPageControl 的默认样式是几个小圆点,系统没有提供属性供我们自定义这几个小圆点的样式,不过我们依然可以使用KVC来自定义PageControl的显示样式 UIPageControl *p ...

  7. PHP中spl_autoload_register()函数

    spl_autoload_register — 注册给定的函数作为 __autoload 的实现 官方地址:http://php.net/manual/zh/function.spl-autoload ...

  8. 7个Linux和Ubuntu下的免费CSS编辑器

    一个好的编辑器是世界上所有程序员和web开发人员梦寐以求的东西.代码编辑器和集成开发环境是程序员工作时的左膀右臂.还在纠结使用什么编辑器么?下面我们将推荐7个主要用于Linux操作系统的免费CSS代码 ...

  9. AngularJS 使用ngOption实现下拉列表

    最近使用到了ngOption实现下拉选择列表,由于需要实现分组等功能,百度了下没有太好的文章,就百度到一篇英文的帖子,按照其中的代码很顺利的搞定了. 本篇根据文中代码,详细讲述下如何实现下拉列表 更多 ...

  10. winServer2003除默认端口外的其他端口只能本地访问,关闭防火墙即可

    winServer2003除默认端口外的其他端口只能本地访问,关闭防火墙即可