• 【洛谷4093】[HEOI2016/TJOI2016] 序列(CDQ分治)


    点此看题面

    • 给定一个长度为(n)的序列(a),给定(m)个条件形如(a_x)可以变成(y)
    • 一种情况下只有最多一个值可能发生变化,求一个最长子序列,满足在所有情况下它都单调不降。
    • (nle10^5)

    读清题面!

    一开始看错题面,没有看到一次最多一个值可能发生变化的限制,想自闭了。

    随手点开洛谷讨论一看一堆人说数据太水,题目读错都能水到好多分。

    本以为他们是小丑,居然会有这么多人都把题目读错了,然后重新看了遍题面,发现小丑竟是我自己。。。

    三维偏序

    只有一个值可能发生变化就非常简单了,记录一下每个位置可能达到的最小值(Mn_i)和最大值(Mx_i)

    两个位置(i,j)(i<j))能同时被选入子序列,当且仅当(a_ile Mn_j)(j)发生了变化)且(Mx_ile a_j)(i)发生了变化)。

    粗略一看,这似乎是四维偏序,不,甚至是跨维度偏序,好像非常诡异。

    但实际上,关于下标这一维的顺序是比较明确的,而一旦确定了(i<j),我们就可以把(i)(a,Mx)分别看作二三维,(j)(Mn,a)分别看作二三维,就变成了一个三维偏序问题。

    所以直接上(CDQ)分治即可。

    代码:(O(nlog^2n))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 100000
    using namespace std;
    int n,m,f[N+5];struct Data
    {
    	int p,x,Mn,Mx;I Data(CI i=0,CI a=0,CI b=0,CI c=0):p(i),x(a),Mn(b),Mx(c){}
    	I bool operator < (Con Data& o) Con {return p<o.p;}
    }s[N+5];
    I bool cx(Con Data& x,Con Data& y) {return x.x<y.x;}
    I bool cMn(Con Data& x,Con Data& y) {return x.Mn<y.Mn;}
    I bool cMx(Con Data& x,Con Data& y) {return x.Mx<y.Mx;}
    namespace FastIO
    {
    	#define FS 100000
    	#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
    	char oc,FI[FS],*FA=FI,*FB=FI;
    	Tp I void read(Ty& x) {x=0;W(!isdigit(oc=tc()));W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));}
    	Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
    }using namespace FastIO;
    struct TreeArray
    {
    	int a[N+5];I void C(RI x) {W(x<=n&&a[x]) a[x]=0,x+=x&-x;}//从x开始清空
    	I void U(RI x,CI v) {W(x<=N&&a[x]<v) a[x]=v,x+=x&-x;}//单点修改
    	I int Q(RI x,RI t=0) {W(x) t=max(t,a[x]),x-=x&-x;return t;}//询问前缀最大值
    }T;
    I void CDQ(CI l,CI r)//CDQ分治,以下标为第一维
    {
    	if(l==r) return;RI mid=l+r>>1;CDQ(l,mid);//先做左区间
    	RI i=l,j=mid+1;for(sort(s+l,s+mid+1,cx),sort(s+mid+1,s+r+1,cMn);j<=r;//按照各自的第二维排序
    		f[s[j].p]=max(f[s[j].p],T.Q(s[j].x)),++j) W(i<=mid&&s[i].x<=s[j].Mn) T.U(s[i].Mx,f[s[i].p]+1),++i;//双指针,根据各自的第三维在树状数组上操作
    	W(--i>=l) T.C(s[i].Mx);sort(s+mid+1,s+r+1),CDQ(mid+1,r);//清空,重新将右区间按第一维排序,再做右区间
    }
    int main()
    {
    	RI i;for(read(n,m),i=1;i<=n;++i) read(s[i].x),s[i].Mn=s[i].Mx=s[i].x,f[s[i].p=i]=1;
    	RI x,y;for(i=1;i<=m;++i) read(x,y),s[x].Mn=min(s[x].Mn,y),s[x].Mx=max(s[x].Mx,y);//记录每个位置能达到的最小值和最大值
    	RI t=0;for(CDQ(1,n),i=1;i<=n;++i) t=max(t,f[i]);return printf("%d
    ",t),0;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    T4文本模板转换过程
    ARKit从入门到精通(6)-ARSession介绍
    ARKit从入门到精通(5)-ARScnView介绍
    ARKit从入门到精通(4)-ARKit全框架API大全
    ARKit从入门到精通(3)-ARKit自定义实现
    ARKit从入门到精通(2)-ARKit工作原理及流程介绍
    ARKit从入门到精通(1)-ARKit初体验
    ios系统中各种设置项的url链接
    iOS 检测网络状态 自动判断 认为提示网络改变
    ios 根据scrollview滑动的偏移计算滑动到第几页算法(不同需求不同计算)
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu4093.html
Copyright © 2020-2023  润新知