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

本蒟蒻第一道\(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;
} 

原文地址:https://www.cnblogs.com/h-lka/p/12005762.html

时间: 2024-08-22 22:01:59

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

弱省胡策系列简要题解

现在不是非常爽,感觉智商掉没了,就整理一下最近弱省胡策的题目吧. 其实题目质量还是很高的. 如果实在看不懂官方题解,说不定这里bb的能给您一些帮助呢? [弱省胡策]Round #0 A 20%数据,O(n4)傻逼dp. 40%数据,O(n3)傻逼dp. 100%数据,令f(x1,y1,x2,y2)表示从(x1,y1)走到(x2,y2)的路径条数.于是所有路径就是f(1,2,n?1,m)×f(2,1,n,m?1).然而两条路径可能在中间的某个点相交,我们找出最早的交点,并在这个交点互换两条路径的后

【弱校胡策】2016.4.14 (bzoj2164)最短路+状压DP+矩阵乘法+高斯消元+树链剖分+线段树+背包DP

cyyz&qhyz&lwyz&gryz弱校胡策 命题人:cyyz ws_fqk T3暴力写挫了 50+10+0滚粗辣! 奇妙的约会(appointment.cpp/c/pas) [问题描述] DQS和sxb在网上结识后成为了非常好的朋友,并且都有着惊人 的OI水平.在NOI2333的比赛中,两人均拿到了金牌,并保送进入 HU/PKU.于是两人决定在这喜大普奔的时刻进行面基. NOI2333参赛选手众多,所以安排了n个考点,DQS在1号考点, 而sxb在n号考点.由于是举办全国性赛事

【弱省胡策】Round #6 String 解题报告

感觉这个题好神啊. 首先我们只管 $a = b$ 的情况,那么我们自然就可以把这个串对 $a$ 取模,然后用 KMP 求出能弄出几个其他的 B 串. 具体就是把串先倍长,然后倒过来,然后求 $Next$ 数组,然后从 $2n$ 开始沿着 $Next[]$ 跳,直到跳到 $\le n$ 的时候停止,看哪些位置被跳到了,哪些位置就是合法的. 问题是现在 $a \neq b$ 怎么办..? 我猜啊,我们可以求出限制是 $a$ 的倍数时,哪些 B 串是合法的,再求出限制是 $b$ 的倍数是,哪些是合法的

【弱省胡策】Round #7 Rectangle 解题报告

orz PoPoQQQ 的神题. 我的想法是:给每一个高度都维护一个 $01$ 序列,大概就是维护一个 $Map[i][j]$ 的矩阵,然后 $Map[i][j]$ 表示第 $i$ 根柱子的高度是否 $\ge j$. 那么怎么维护 $Map[i][j]$ 呢..? 首先我们把柱子按照高度从小到大排序,然后依次给每个高度建主席树,初始时 $Map[i][0]$ 全是 $1$,然后如果当前高度 $i$ 比某个柱子 $j$ 的高度要大了,那么就单点修改 $Map[i][j]$,然后这个就是主席树动态开

【弱省胡策】Round #5 Handle 解题报告

这个题是我出的 sb 题. 首先,我们可以得到: $$A_i = \sum_{j=i}^{n}{j\choose i}(-1)^{i+j}B_j$$ 我们先假设是对的,然后我们把这个关系带进来,有: $$B_i = \sum_{j=i}^{n}{j\choose i}A_j = \sum_{j=1}^{n}{j\choose i}\sum_{k=j}^{n}{k\choose j}(-1)^{j+k}B_k = \sum_{j=i}^{n}B_j\sum_{k=i}^{j}{j\choose k

【弱省胡策】Round #5 Construct 解题报告

这个题是传说中的 Hack 狂魔 qmqmqm 出的构造题.当然要神. 这个题的本质实际上就是构造一个图,然后使得任意两点间都有长度为 $k$ 的路径相连,然后对于任意的 $i < k$,都存在两个点使得这两个点没有长度为 $i$ 的路径相连. 我的构造方法就是: 首先给每个点连一个自环. 构造一个大小为 $n-k+1$ 的团. 然后剩下的点造成一条链并与 $n-k+1$ 号点相连. 这样的解是一组可行解. 时间复杂度 $O(n^2)$,空间复杂度 $O(1)$. 1 #include <cs

校内胡策(唯一一个想出来的)

2 第一题 (third.cpp/c/pas) 题目描述 小 R 最近沉迷于一个叫做 Slay.one 的游戏. 在这个游戏中,每一局有若干人参加,最终会产生一个优胜者.优胜者会获得 一个成就点. 现在小 R 已经利用某种手段得知了每场游戏有哪些人参加.假设所有人最初成 就点都是 0 ,小 R 想要知道所有游戏结束之后成就点最多的人至少有多少成就点. 校内胡策(唯一一个想出来的) 原文地址:https://www.cnblogs.com/Lance1ot/p/9445468.html

【胡策篇】题解

和泉纱雾与烟花大会 题目来源: UOJ 192 最强跳蚤 (只改了数据范围) 官方题解: 在这里哦~(说的很详细了 我都没啥好说的了) 题目大意: 求树上各边权乘积是完全平方数的路径数量. 这种从\(n^2\)条路径中找出满足xx条件的路径的条数的题, 我们可以根据常识判断要用到点分治. 不过这题并没有用到点分治, 这个一会再说, 我们先来看部分分. 哎呀其实这题好多部分分我都不会写(捂脸 算法1: 直接乘边权处理显然是不行哒, 怕是\(w\leq2\)怕是都要用到高精度了(什么你说\(w\le

山西胡策 #7

A. B. C. 题意:给出(i, j)之类的约束表示要j必须先i,问1尽量靠前.2尽量靠前.3尽量靠前以此类推的最优方案,或输出无解. #include <bits/stdc++.h> using namespace std; const int N=100005; int cnt, ihead[N], in[N], ans[N], tot, n, m; struct E { int next, to; }e[N]; void add(int x, int y) { e[++cnt]=(E)