zoukankan      html  css  js  c++  java
  • P3769 [CH弱省胡策R2]TATT(cdq套cdq)

    P3769 [CH弱省胡策R2]TATT

    cdq分治只会板子就来自己yy cdq套cdq的题(虽然也是板子)。被kdt吊打了2倍常数。不过没有确定出题人是否卡满了kdt,等会我去卡卡。

    能自己yy出做法非常高兴,然后因为一个sb错误调了2h

    首先按照第一维排序。然后仿照最长上升子序列定义状态:(dp_i=max{dp_j+1}(a_jle a_i,b_jle b_i,c_jle c_i,d_jle d_i))

    由于排序,所以 (a_jle a_i) 一定满足。

    接下去考虑怎么限制三维。

    由于是dp,记得中序遍历分治树,因为计算右区间的时候要求所有左区间的贡献已经计算完成,不然 (dp_i) 会偏小。

    设当前分治到 ([l,r]) ,按照第二维排序后给点打标记,([l,mid]) 内的标记为 (1)([mid+1,r]) 内的标记为 (0)

    然后直接二维偏序(三、四两维)转移,在过程中只统计标记为 (1) 的对标记为 (0) 的点的贡献,这样就能带上第二维的限制了。

    所以,如果再多几维,那么多打几层标记即可。当然再多几维就不会用cdq分治了qwq

    • 小坑:有重复的点,先去重,然后给点赋权值,权值 (w) 为重复的个数,转移改成 (dp_i=max{dp_j+w})

    • 我写代码时候一个奇葩的坑:一开始没注意到只用离散化d,把abcd一起离散化了,然后WA82。原因是树状数组忘记开 (4) 倍空间,然后因为洛谷的神秘O2高性能没有RE调了2h,不然早过了/kk

    复杂度是两层cdq+树状数组=(O(nlog^3 n)) ,常数不大。但是为啥kdt (O(n^{frac{5}{3}})) 会把这个(log^3) 吊起来打啊/kk

    #include<bits/stdc++.h>
    using namespace std;
    #define fi first
    #define se second
    #define mkp(x,y) make_pair(x,y)
    #define pb(x) push_back(x)
    #define sz(v) (int)v.size()
    typedef long long LL;
    typedef double db;
    template<class T>bool ckmax(T&x,T y){return x<y?x=y,1:0;}
    template<class T>bool ckmin(T&x,T y){return x>y?x=y,1:0;}
    #define rep(i,x,y) for(int i=x,i##end=y;i<=i##end;++i)
    #define per(i,x,y) for(int i=x,i##end=y;i>=i##end;--i)
    inline int read(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=0;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return f?x:-x;
    }
    const int N=50005;
    int n,n_,len,lsh[N],dp[N],ans,tr[N];
    struct node{
    	int a,b,c,d,s,op,id;
    	node(){a=b=c=d=op=id=0;}
    	inline bool operator == (const node&t)const{return a==t.a&&b==t.b&&c==t.c&&d==t.d;}
    }a[N],b[N];
    inline bool cmp1(const node&a,const node&b){return a.a!=b.a?a.a<b.a:a.b!=b.b?a.b<b.b:a.c!=b.c?a.c<b.c:a.d<b.d;}
    inline bool cmp2(const node&a,const node&b){return a.b!=b.b?a.b<b.b:a.a!=b.a?a.a<b.a:a.c!=b.c?a.c<b.c:a.d<b.d;}
    inline bool cmp3(const node&a,const node&b){return a.c<b.c;}
    void upd(int x,int d){for(int i=x;i<=len;i+=i&-i)ckmax(tr[i],d);}
    int ask(int x){int res=0;for(int i=x;i>0;i-=i&-i)ckmax(res,tr[i]);return res;}
    void clr(int x){for(int i=x;i<=len;i+=i&-i)tr[i]=0;}
    void cdq2(int l,int r){
    	if(l==r)return;
    	int mid=(l+r)>>1,i,j;
    	cdq2(l,mid),sort(a+l,a+mid+1,cmp3),sort(a+mid+1,a+r+1,cmp3);
    	for(i=mid+1,j=l;i<=r;++i){
    		for(;a[j].c<=a[i].c&&j<=mid;++j)if(a[j].op)upd(a[j].d,dp[a[j].id]);
    		if(!a[i].op)ckmax(dp[a[i].id],ask(a[i].d)+a[i].s);
    	}
    	for(--j;j>=l;--j)clr(a[j].d);
    	sort(a+mid+1,a+r+1,cmp2);
    	cdq2(mid+1,r);
    }
    void cdq1(int l,int r){
    	if(l==r)return;
    	int mid=(l+r)>>1;
    	cdq1(l,mid);
    	for(int i=l;i<=r;++i)a[i].op=i<=mid;
    	sort(a+l,a+r+1,cmp2);
    	cdq2(l,r);
    	sort(a+l,a+r+1,cmp1);
    	cdq1(mid+1,r);
    }
    signed main(){
    	n_=read();
    	rep(i,1,n_)b[i].a=read(),b[i].b=read(),b[i].c=read(),b[i].d=lsh[++len]=read();
    	sort(lsh+1,lsh+len+1),len=unique(lsh+1,lsh+len+1)-lsh-1;
    	rep(i,1,n_)b[i].d=lower_bound(lsh+1,lsh+len+1,b[i].d)-lsh;
    	sort(b+1,b+n_+1,cmp1);
    	for(int i=1,j=1;i<=n_;i=++j){
    		while(j<n_&&b[j+1]==b[i])++j;
    		a[++n]=b[i],a[n].s=j-i+1,a[n].id=n,dp[n]=a[n].s;
    	}
    	cdq1(1,n);
    	for(int i=1;i<=n;++i)ckmax(ans,dp[i]);
    	printf("%d
    ",ans);return 0;
    }
    
  • 相关阅读:
    codefoces 1405 D Tree Tag
    洛谷P3413 萌数
    数位DP模板
    leetcode 统计所有可行路径
    Josephus Transform 加速置换
    牛客IOI周赛18-提高组 排列
    Find a way HDU
    Oil Deposits HDU
    Fire! UVA
    Pots POJ
  • 原文地址:https://www.cnblogs.com/zzctommy/p/14237406.html
Copyright © 2011-2022 走看看