本蒟蒻第一道\(K-D-Tree\)维护\(dp\)

Question

题目大意:求一条路径,使得其四个维度单调不降。

先排序消掉一维再说。

对于每一个点,初始的时候绝对长度是1啊。于是,先赋值一个1,对于每一个点。

设计\(dp\)数组

\[f[i]=max_{f[j]}(a[j]<=a[i],b[j]<=b[i],c[j]<=c[i],d[j]<=d[i])
\]

那问题就转为,对于每一个点,如何求出在它之前的最大\(f[i]\)值。

发现问题类似于三维偏序,正好\(K-D-Tree\)硬刚即可:

对于每一个点,维护这个点的\(f[i]\)值,以及这个点的四个坐标;而树上只需要维护三个维度的上下界以及区间\(MAX\),动态\(query\)即可。

(有点懵的是,不能提前处理排序后的第一个点,而必须对所有点一次插入)

\(hole:\)对于\(sort\)函数的\(cmp\)函数,应该以四个维度分别为第\(1,2,3,4\)关键字排顺序,而不是只排一个。

\(Code:\)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=5e5+10;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')w=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
s=(s<<1)+(s<<3)+(ch^48);
ch=getchar();
}
return s*w;
}
struct pt{
int x[4],cnt;
}p[MAXN];
#define Alpha 0.75
#define inf 2147483647
struct node{
int mx[3],mi[3],siz,maxn;
pt c;
}tr[MAXN];
int n,m,D,rt,tot,top,ans=-inf;
int ls[MAXN],rs[MAXN],rub[MAXN];
int operator<(pt a,pt b){return a.x[D]<b.x[D];}
inline void pushup(int x){
int l=ls[x],r=rs[x];
tr[x].siz=tr[l].siz+tr[r].siz+1;
for(int i=0;i<=2;++i){
tr[x].mi[i]=tr[x].mx[i]=tr[x].c.x[i];
tr[x].maxn=tr[x].c.cnt;
if(l)tr[x].mi[i]=min(tr[x].mi[i],tr[l].mi[i]),
tr[x].mx[i]=max(tr[x].mx[i],tr[l].mx[i]),
tr[x].maxn=max(tr[x].maxn,tr[l].maxn);
if(r)tr[x].mi[i]=min(tr[x].mi[i],tr[r].mi[i]),
tr[x].mx[i]=max(tr[x].mx[i],tr[r].mx[i]),
tr[x].maxn=max(tr[x].maxn,tr[r].maxn);
}
}
inline bool cmp(pt a,pt b){
return a.x[3]<b.x[3]||(a.x[3]==b.x[3]&&a.x[2]<b.x[2])||(a.x[3]==b.x[3]&&a.x[2]==b.x[2]&&a.x[1]<b.x[1])||(a.x[3]==b.x[3]&&a.x[2]==b.x[2]&&a.x[1]==b.x[1]&&a.x[0]<b.x[0]);
}
inline int New(){
if(top)return rub[top--];
else return ++tot;
}
int build(int l,int r,int d){
if(l>r)return 0;
int x=New(),mid=l+r>>1;
D=d;nth_element(p+l,p+mid,p+r+1);
tr[x].c=p[mid];ls[x]=build(l,mid-1,(d+1)%3);
rs[x]=build(mid+1,r,(d+1)%3);pushup(x);return x;
}
void clear(int x,int pos){
if(ls[x])clear(ls[x],pos);
p[pos+tr[ls[x]].siz+1]=tr[x].c;rub[++top]=x;
if(rs[x])clear(rs[x],pos+tr[ls[x]].siz+1);
}
void check(int &x,int d){
double C=Alpha*(double)(tr[x].siz);
if(C<(double)tr[ls[x]].siz||C<(double)tr[rs[x]].siz){clear(x,0);x=build(1,tr[x].siz,d);}
}
void Ins(int &x,pt s,int d){
if(!x){x=New();ls[x]=rs[x]=0;tr[x].c=s;pushup(x);return;}
if(s.x[d]<=tr[x].c.x[d])Ins(ls[x],s,(d+1)%3);
else Ins(rs[x],s,(d+1)%3);
pushup(x);check(x,d);
}
int f[MAXN];
bool Check(int x,pt s){
int fg=0;
for(int i=0;i<=2;++i){
if(tr[x].mx[i]>s.x[i]){
fg=1;break;
}
}
if(fg)return false;
else return true;
}
bool CK(int x,pt s){
int fg=0;
for(int i=0;i<=2;++i){
if(tr[x].mi[i]>s.x[i])return true;
}
return false;
}
inline bool ck(pt a,pt b){
int fg=1;
for(int i=0;i<=2;++i){
if(a.x[i]>b.x[i]){
fg=0;
break;
}
}
return fg;
}
int query(int x,pt a){
int res=-inf;
if(CK(x,a))return 0;
else if(Check(x,a))return tr[x].maxn;
else {
if(ck(tr[x].c,a))res=max(res,tr[x].c.cnt);
res=max(query(ls[x],a),res);res=max(query(rs[x],a),res);
return res;
}
}
int main(){
n=read();
for(int i=1;i<=n;++i){
p[i].x[0]=read(),p[i].x[1]=read(),p[i].x[2]=read(),p[i].x[3]=read();
}
for(int i=1;i<=n;++i)f[i]=1;
sort(p+1,p+n+1,cmp);
for(int i=1;i<=n;++i){
f[i]+=query(rt,p[i]);
// cout<<"当前点f[i]:"<<i<<"<- ->"<<f[i]<<endl;
p[i].cnt=f[i];
Ins(rt,p[i],0);
}
for(int i=1;i<=n;++i)ans=max(ans,f[i]);
printf("%d\n",ans);
return 0;
}

【题解】[CH弱省胡策R2]TATT的更多相关文章

  1. luoguP3769 [CH弱省胡策R2]TATT

    luoguP3769 [CH弱省胡策R2]TATT PS:做这题前先切掉 P4148简单题,对于本人这样的juruo更助于理解,当然dalao就当练练手吧 题目大意: 现在有n个四维空间中的点,请求出 ...

  2. [CH弱省胡策R2]TATT

    description 洛谷 data range \[ n\le 5\times 10^4\] solution 这就是四维偏序了... 好象时间复杂度是\(O(n^{\frac{5}{3}})\) ...

  3. [Luogu3769][CH弱省胡策R2]TATT

    luogu 题意 其实就是四维偏序. sol 第一维排序,然后就只需要写个\(3D-tree\)了. 据说\(kD-tree\)的单次查询复杂度是\(O(n^{1-\frac{1}{k}})\).所以 ...

  4. 洛谷3769[CH弱省胡策R2]TATT (KDTree)(四维LIS)

    真是一个自闭的题目(调了一个上午+大半个下午) 从\(WA\)到\(WA+TLE\)到\(TLE\)到\(AC\) 真的艰辛. 首先,这个题,我们可以考虑直接上四维KDTree来解决. 对于kdtre ...

  5. 【弱省胡策】Round #5 Count

    [弱省胡策]Round #5 Count 太神仙了. \(DP\)做法 设\(f_{n,m,d,k}\)表示\(n*m\)的矩阵,填入第\(k\)个颜色,并且第\(k\)个颜色最少的一列上有\(d\) ...

  6. 弱省胡策 Magic

    弱省胡策 Magic 求\(n\)个点\(n\)的条边的简单联通图的个数. 毒瘤,还要写高精. 我们枚举环的大小\(k\),\(\displaystyle ans=\sum_{k=3}^nC_n^k ...

  7. 【ContestHunter】【弱省胡策】【Round0】(A)&【Round1】(B)

    DP+容斥原理or补集转化?/KD-Tree 唔……突然发现最早打的两场(打的最烂的两场)没有写记录……(太烂所以不忍记录了吗... 还是把搞出来了的两道题记录一下吧= =勉强算弥补一下缺憾…… Ro ...

  8. 【ContestHunter】【弱省胡策】【Round3】(C)

    容斥原理+Fib Orz HE的神犇们 蒟蒻只能改出来第三题……实在太弱 官方题解:http://pan.baidu.com/s/1o6MdtQq fib的神奇性质……还有解密a[i]的过程……这里就 ...

  9. 【ContestHunter】【弱省胡策】【Round2】

    官方题解:http://wyfcyx.is-programmer.com/posts/95490.html A 目前只会30分的暴力……DP好像很神的样子0.0(听说可以多次随机强行算? //Roun ...

随机推荐

  1. Codeforces 1321D Navigation System

    题意 有个人要从\(s\)走到\(t\),经过的路径给定.导航系统每次会显示当前节点到\(t\)的最短路,有多条就显示其中之一.这个人如果按照导航走,那么啥都没变.如果没有按导航走导航就会重新导航.问 ...

  2. Resis常用命令及数据类型

    1.下载Windows环境redis安装: 2.下载jar包: commons-pool2-2.4.2.jar jedis-2.9.0.jar 3.项目结构: 4.代码说明: package com. ...

  3. 用Maven给一个Maven工程打包,使用阿里云镜像解决mvn clean package出错的问题,使用plugin解决没有主清单属性的问题

    本来在STS里做了一个极简Maven工程,内中只有一个Main方法的Java类,然后用新装的Maven3.6.3给它打包. 结果,Maven罢工,输出如下: C:\personal\programs\ ...

  4. IDEA下Git分支开发

    IDEA下Git分支开发使用 1.新建本地开发分支 VCS-->git-->branches-->New Branch,输入分支名字,如branch_test,点击OK后本地开发分支 ...

  5. 深入理解 vue 中 scoped 样式作用域的规则

    哈喽!大家好!我是木瓜太香,今天我们来聊一个 vue 的样式作用域的问题,通常我们开发项目的时候是要在 style 上加上 scoped 来起到规定组件作用域的效果的,所以了解他们的规则也是很有必要的 ...

  6. Linux curl携带cookie测试接口

    问题: 休息在家,被告知要启动测试环境的一个定时任务,但是服务器在内网,连上vpn只能访问内网的开发环境,无法访问测试环境,于是进开发环境服务器,ping测试环境的ip,发现是通的,于是想到通过开发环 ...

  7. 2020年 .NET ORM 完整比较、助力选择

    .NET ORM 前言 为什么要写这篇文章? 希望针对 SEO 优化搜索引擎,让更多中国人知道并且使用.目前百度搜索 .NET ORM 全是 sqlsugar,我个人是无语的,每每一个人进群第一件事就 ...

  8. 5 分钟带你掌握 Makefile 分析

    摘要:Makefile是一个名为GNU-Make软件所需要的脚本文件,该脚本文件可以指导Make软件控制arm-gcc等工具链去编译工程文件最终得到可执行文件,几乎所有的Linux发行版都内置了GNU ...

  9. linux下限定连接ip和端口

    1.限制端口 vim /etc/ssh/sshd_config 修改连接端口 修改之后重启sshd服务 service sshd restart 再次连接时就需要使用修改后的端口去连接了 备注:判断修 ...

  10. 程序员你是如何降低NPE的?

    程序员,如果系统突然报了一个空指针异常,你肯定像吞了一只苍蝇一样尴尬. 那么如何在日常开发过程中降低NPE? 问题 回答 现状 返回空值会出现大量的空指针异常 目的 改进方法的返回值,降低出现空指针异 ...