luoguP3769 [CH弱省胡策R2]TATT

PS:做这题前先切掉 P4148简单题,对于本人这样的juruo更助于理解,当然dalao就当练练手吧

题目大意: 现在有n个四维空间中的点,请求出一条最长的路径,满足任意一维坐标都是单调不降的

偏模板的K-D Tree

题目没规定起点,则从任意一点出发,按维度优先级以及每个维度坐标为关键字排序,

每点作为终点查询一次,再插入,其他就是模板化的代码了

这里用到了一个小技巧,就是初始化将子树0的值赋值,避免过多的特判,使代码更加简洁

for(LL i=0;i<=3;++i)
tree[0].mi[i]=inf,tree[0].mx[i]=-inf; tree[0].maxn=-inf;

My complete code:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long LL;
const LL maxn=1e5+10;
const LL inf=1e9;
inline LL read(){
LL x=0,f=1; char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=-1; c=getchar();
}
while(c>='0'&&c<='9'){
x=x*10+c-'0'; c=getchar();
}
return x*f;
}
struct node{
LL son[2],d[4],maxn,size,val,mi[4],mx[4];
}tree[maxn],t2[maxn],tmp;
bool operator < (node g1,node g2){
for(LL i=0;i<=3;++i){
if(g1.d[i]<g2.d[i]) return 1;
if(g1.d[i]>g2.d[i]) return 0;
}return 0;
}
LL n,ans,ans_maxn,top,cnt,root,WD; LL sta[maxn];
inline void update(LL now){
LL son0=tree[now].son[0],son1=tree[now].son[1];
for(LL i=0;i<=3;++i){
tree[now].mi[i]=min(min(tree[son0].mi[i],tree[son1].mi[i]),tree[now].d[i]);
tree[now].mx[i]=max(max(tree[son0].mx[i],tree[son1].mx[i]),tree[now].d[i]);
}
tree[now].maxn=max(tree[now].val,max(tree[son0].maxn,tree[son1].maxn));
tree[now].size=tree[son0].size+tree[son1].size+1;
}
inline bool cmp(LL g1,LL g2){
return tree[g1].d[WD]<tree[g2].d[WD];
}
LL build(LL l,LL r,LL wd){
if(l>r)
return 0;
LL mid=(l+r)>>1;
WD=wd;
nth_element(sta+l,sta+mid,sta+r+1,cmp);
LL now=sta[mid];
tree[now].son[0]=build(l,mid-1,(wd+1)%4);
tree[now].son[1]=build(mid+1,r,(wd+1)%4);
update(now);
return now;
}
void pai(LL now){
if(!now)
return;
sta[++top]=now;
LL son0=tree[now].son[0],son1=tree[now].son[1];
pai(son0); pai(son1);
}
inline void check(LL &now,LL wd){
LL son0=tree[now].son[0],son1=tree[now].son[1];
if(tree[now].size*0.75<tree[son0].size||tree[now].size*0.75<tree[son1].size){
top=0;
pai(now);
now=build(1,tree[now].size,wd);
}
}
void insert(LL &now,LL wd){
if(!now){
now=++cnt;
tree[now]=tmp;
for(LL i=0;i<=3;++i)
tree[now].mi[i]=tree[now].mx[i]=tree[now].d[i];
tree[now].maxn=tree[now].val; tree[now].size=1;
return;
}
if(tmp.d[wd]<tree[now].d[wd])
insert(tree[now].son[0],(wd+1)%4);
else
insert(tree[now].son[1],(wd+1)%4);
update(now);
check(now,wd);
} inline LL dis(node g1,node g2){
for(LL i=0;i<=3;++i)
if(g1.d[i]>g2.d[i])
return 0;
return g1.val;
}
inline LL into(LL now){
if(!now)
return 0;
LL sum=0;
for(LL i=0;i<=3;++i)
if(tree[now].mx[i]<=tmp.d[i])
++sum;
if(sum==4)
return 4;
for(LL i=0;i<=3;++i)
if(tree[now].mi[i]>tmp.d[i])
return 0;
return 1;
}
void query(LL now){
ans=max(dis(tree[now],tmp),ans);
LL son0=tree[now].son[0],son1=tree[now].son[1];
LL dl=into(son0),dr=into(son1);
if(dl==4)
ans=max(tree[son0].maxn,ans);
else if(dl&&ans<tree[son0].maxn)
query(son0);
if(dr==4)
ans=max(tree[son1].maxn,ans);
else if(dr&&ans<tree[son1].maxn)
query(son1);
}
int main(){
n=read();
for(LL i=1;i<=n;++i){
for(LL j=0;j<=3;++j)
t2[i].d[j]=read();
t2[i].val=1;
}
sort(t2+1,t2+n+1);
for(LL i=0;i<=3;++i)
tree[0].mi[i]=inf,tree[0].mx[i]=-inf; tree[0].maxn=-inf;
for(LL i=1;i<=n;++i){
ans=0;
tmp=t2[i];
query(root);
tmp.val+=ans;
ans_maxn=max(tmp.val,ans_maxn);
insert(root,0);
}
printf("%lld",ans_maxn);
return 0;
}

  

luoguP3769 [CH弱省胡策R2]TATT的更多相关文章

  1. [CH弱省胡策R2]TATT

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

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

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

  3. 【题解】[CH弱省胡策R2]TATT

    本蒟蒻第一道\(K-D-Tree\)维护\(dp\) Question 题目大意:求一条路径,使得其四个维度单调不降. 先排序消掉一维再说. 对于每一个点,初始的时候绝对长度是1啊.于是,先赋值一个1 ...

  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. 【重点突破】——第三方绘图工具FusionCharts.js的使用详解

    一.引言 项目组中,经常会因为绘制图表的繁杂度,衡量会不会使用第三方绘图工具,如果自己做很困难,成本使用高于第三方绘图工具库,就会使用.很多人使用的是Chart.js,因为它是免费使用的,不过,缺点就 ...

  2. 微信小程序-获取用户信息(getUserInfo)

    当小程序抹杀掉这个接口的时候,多少人心凉了.. 作为一个初级web前端开发,我是更加懵逼,小程序员跑路了... 当时以及现在用的办法就是: 1.增加一个登陆或授权页 2.上线以后自动获取 3.增加一个 ...

  3. GetDlgItem() 出现错误

    写MFC程序ASSERT(IsWindow(pTemp->m_hWnd))报错 CRect rect; CWnd *pWnd = GetDlgItem(IDC_picture);//IDC_pi ...

  4. java debug

    java debug 模式下各button作用 F5:跳入方法  Step Into F6:向下逐行调试  Step Over F7:跳出方法  Step Return F8:直接跳转到下一个断点 D ...

  5. MongoDB入门学习(二):MongoDB的基本概念和数据类型

    上一篇讲了MongoDB的安装和管理,当中涉及到了一些概念,数据结构另一些API的调用,不知道的没关系,事实上非常easy,这篇会简介一下. 1.文档 文档是MongoDB的核心概念.多个键值对有序的 ...

  6. Web安全系列(三):XSS 攻击进阶(挖掘漏洞)

    前言 在前些章节 (web安全系列(一):XSS 攻击基础及原理)以及(Web安全系列(二):XSS 攻击进阶(初探 XSS Payload))中,我详细介绍了 XSS 形成的原理以及 XSS 攻击的 ...

  7. nightwatch 切换窗口

    .switchWindow() Change focus to another window. The window to change focus to may be specified by it ...

  8. Qt on Android:将Qt调试信息输出到logcat中

    版权全部 foruok .如需转载敬请注明出处(http://blog.csdn.net/foruok). 假设你在目标 Android 设备上执行了 Qt on Android 应用,你可能希望看到 ...

  9. 2014acm亚洲区域赛陕西赛总结

    这次是第一次出来到外面比赛,一切都是非常新鲜的,带着新鲜来到了古城西安.首先感觉就是志愿者一点都不热情.一副爱理不理的,这不是有违我大西北人的热情好客么. 直接说比赛吧. 第一天热身赛,出了两道非常水 ...

  10. inflate, findViewById与setContentView的差别与联系

    protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentV ...