COGS 2479 偏序 题解
【题意】
给定一个有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 偏序 题解的更多相关文章
- COGS 2479. [HZOI 2016]偏序 [CDQ分治套CDQ分治 四维偏序]
传送门 给定一个有n个元素的序列,元素编号为1~n,每个元素有三个属性a,b,c,求序列中满足i<j且ai<aj且bi<bj且ci<cj的数对(i,j)的个数. 对于100%的 ...
- COGS 2479. [HZOI 2016] 偏序 (CDQ套CDQ)
传送门 解题思路 四维偏序问题,模仿三维偏序,第一维排序,第二维CDQ,最后剩下二元组,发现没办法处理,就继续嵌套CDQ分治.首先把二元组的左右两边分别打上不同的标记,因为统计答案时只统计左边对右边的 ...
- BZOJ3262:陌上花开 & 洛谷3810:三维偏序——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=3262 https://www.luogu.org/problemnew/show/3810 Desc ...
- CDQ分治学习笔记(三维偏序题解)
首先肯定是要膜拜CDQ大佬的. 题目背景 这是一道模板题 可以使用bitset,CDQ分治,K-DTree等方式解决. 题目描述 有 nn 个元素,第 ii 个元素有 a_iai.b_ibi.c_ ...
- COGS 2479 奇怪的姿势卡♂过去 (bitset+折半)
思路: 此题显然是CDQ套CDQ套树套树 (然而我懒) 想用一种奇怪的姿势卡过去 就出现了以下解法 5w*5w/8的bitset hiahiahia 但是空间会爆怎么办啊- 折半~ 变成5w*2.5w ...
- CDQ分治嵌套模板:多维偏序问题
CDQ分治2 CDQ套CDQ:四维偏序问题 题目来源:COGS 2479 偏序 #define LEFT 0 #define RIGHT 1 struct Node{int a,b,c,d,bg;}; ...
- 四维偏序 CDQ套CDQ
对CDQ深一步的理解 昨天做了一道CDQ,看了一堆CDQ可做的题,今天又做了一道四维偏序 感觉对CDQ的理解又深了一点,故来写一写现在自己对于CDQ的理解 CDQ其实就是实现了这样的一个问题的转化: ...
- 【教程】CDQ套CDQ——四维偏序问题
前言 上一篇文章已经介绍了简单的CDQ分治,包括经典的二维偏序和三维偏序问题,还有带修改和查询的二维/三维偏序问题.本文讲介绍多重CDQ分治的嵌套,即多维偏序问题. 四维偏序问题 给定N( ...
- 几道很Interesting的偏序问题
若干道偏序问题(STL,分块) 找了4道题目 BZOJ陌上花开(权限题,提供洛谷链接) Cogs2479偏序 Cogs2580偏序II Cogs2639偏序++ 作为一个正常人,肯定先看三维偏序 做法 ...
随机推荐
- css 网站变灰色
网站变灰色 html{ -webkit-filter: grayscale(%); -webkit-filter: grayscale(); filter: grayscale(%); filter: ...
- #if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_8_0
头文件处理 #import <UIKit/UIKit.h> #if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_8_0 #else #imp ...
- Unity 下载
Unity历史版本 http://wiki.ceeger.com/unity:history#unity_522f1 UNITY 下载存档 http://unity3d.com/cn/get-unit ...
- Why is applicationhost.config still being added to source control even thought it's in gitignore
Why is applicationhost.config still being added to source control even thought it's in gitignore g ...
- centos 7.0 nginx 1.7.9 安装过程
系统用的是centos 7.0最小化安装 我现在安装完了 写一下步骤 还没完全搞懂 首先安装GCC [root@localhost ~]# yum install -y gcc gcc-c++ 已加载 ...
- GoLang之方法与接口
GoLang之方法与接口 Go语言没有沿袭传统面向对象编程中的诸多概念,比如继承.虚函数.构造函数和析构函数.隐藏的this指针等. 方法 Go 语言中同时有函数和方法.方法就是一个包含了接受者的函数 ...
- MV*模式的个人理解
MV*模式主要解决的问题就是 View代码难以维护的问题. MV*模式将View中的逻辑分离出去,形成一个弱逻辑的易于维护的视图. MV*中的*是Model和View的桥梁,负责保持Model和Vie ...
- Last-Modify和Etag
Last-Modified和Etag Last-Modified是页面文件最后的修改时间,Etag相当于页面文件的hash. http request http respose If ...
- Elasticsearch-PHP 索引操作(转)
索引操作 本节通过客户端来介绍一下索引API的各种操作.索引操作包含任何管理索引本身(例如,创建索引,删除索引,更改映射等等). 我们通过一些常见的操作的代码片段来介绍,然后在表格中列出剩下的方法.R ...
- java 利用反射机制,获取实体所有属性和方法,并对属性赋值
一个普通的实体Person: private int id; private String name; private Date createdTime;...//其它字段// get set方法 . ...