zoukankan      html  css  js  c++  java
  • 【洛谷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;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    chrome浏览器中安装以及使用Elasticsearch head 插件
    windows10 升级并安装配置 jmeter5.3
    linux下部署Elasticsearch6.8.1版本的集群
    【Rollo的Python之路】Python 爬虫系统学习 (八) logging模块的使用
    【Rollo的Python之路】Python 爬虫系统学习 (七) Scrapy初识
    【Rollo的Python之路】Python 爬虫系统学习 (六) Selenium 模拟登录
    【Rollo的Python之路】Python 爬虫系统学习 (五) Selenium
    【Rollo的Python之路】Python 爬虫系统学习 (四) XPath学习
    【Rollo的Python之路】Python 爬虫系统学习 (三)
    【Rollo的Python之路】Python sys argv[] 函数用法笔记
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu4093.html
Copyright © 2011-2022 走看看