• BZOJ4553


    Portal

    Description

    给出一个(n(nleq10^5))个数的数列({a_n})(m(mleq10^5))个形如((x,y))的变化,表示(a_x)可以变成(y)。我们称一个子序列是合法的当且仅当其中至多一个数发生变化后,其仍然是一个不降序列。求最长合法子序列的长度。

    Solution

    (a_i)能变化的最小值为(fr_i),最大值为(to_i)(dp[i])表示以(a_i)结尾的最长合法子序列的长度。则很容易得到:

    [ dp[i]=max{dp[j]}+1 quad (j<i,to_jleq a_i,a_jleq fr_i) $$ 时间复杂度为$O(n^2)$。 考虑如何快速求出满足$to_jleq a_i,a_jleq fr_i$的$j$,可以用k-d树搞(可能被卡常),这里用CDQ分治解决。 每次考虑$dp[L..mid]$对$dp[mid+1..R]$的影响。对于$iin[mid+1,R]$记录三元组$(a_i,fr_i,i)$,对于$jin[L,mid]$记录三元组$(to_j,a_j,j)$,排序后用线段树可搞。具体来说,线段树上区间$[L_0,R_0]$维护满足$a_jin[L_0,R_0]$的$dp[j]$的最大值。排序保证了$to_jleq a_i$,并且询问处于最后。 > 时间复杂度$O(nlog^2n)$。 ##Code ```cpp //序列 #include <algorithm> #include <cstdio> #include <cstring> using namespace std; inline char gc() { static char now[1<<16],*s,*t; if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;} return *s++; } inline int read() { int x=0; char ch=gc(); while(ch<'0'||'9'<ch) ch=gc(); while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc(); return x; } int const N=1e5+10; int const V=N; int n,m; struct rec{int a,fr,to,id;} r[N],r1[N]; int cmpM; bool cmpR(rec x,rec y) { int x1,x2,y1,y2; if(x.id<=cmpM) x1=x.to,x2=x.a; else x1=x.a,x2=x.fr; if(y.id<=cmpM) y1=y.to,y2=y.a; else y1=y.a,y2=y.fr; if(x1==y1) return x2==y2?x.id<y.id:x2<y2; else return x1<y1; } int dp[N]; #define Ls (p<<1) #define Rs ((p<<1)|1) int rt; int maxV[N<<2],tag[N<<2]; void update(int p) {maxV[p]=max(maxV[Ls],maxV[Rs]);} void change(int p,int x) {maxV[p]=tag[p]=x;} void pushdw(int p) {if(tag[p]!=-1) change(Ls,tag[p]),change(Rs,tag[p]),tag[p]=-1;} int L,R; int tr[N]; void ins(int p,int L0,int R0,int x) { if(L==L0&&R0==L) {change(p,max(maxV[p],x)); return;} pushdw(p); int mid=L0+R0>>1; if(L<=mid) ins(Ls,L0,mid,x); else ins(Rs,mid+1,R0,x); update(p); } int query(int p,int L0,int R0) { if(L<=L0&&R0<=R) return maxV[p]; pushdw(p); int mid=L0+R0>>1,res=0; if(L<=mid) res=max(res,query(Ls,L0,mid)); if(mid<R) res=max(res,query(Rs,mid+1,R0)); return res; } void solve(int fr,int to) { if(fr==to) return; int mid=fr+to>>1; solve(fr,mid); for(int i=fr;i<=to;i++) r1[i]=r[i]; cmpM=mid; sort(r1+fr,r1+to+1,cmpR); change(rt,0); for(int i=fr;i<=to;i++) { int t=r1[i].id; if(t<=mid) L=r[t].a,ins(rt,1,V,dp[t]); else L=1,R=r[t].fr,dp[t]=max(dp[t],query(rt,1,V)+1); } solve(mid+1,to); } int main() { n=read(),m=read(); for(int i=1;i<=n;i++) r[i].fr=r[i].to=r[i].a=read(),r[i].id=i; for(int i=1;i<=m;i++) { int x=read(),y=read(); r[x].fr=min(r[x].fr,y),r[x].to=max(r[x].to,y); } rt=1; memset(tag,-1,sizeof tag); for(int i=1;i<=n;i++) dp[i]=1; solve(1,n); int ans=0; for(int i=1;i<=n;i++) ans=max(ans,dp[i]); printf("%d ",ans); return 0; } ```]

  • 相关阅读:
    BlogEngine.Net
    加速Web开发的9款知名HTML5框架
    个人论坛博客的代码
    Android客户端调用Asp.net的WebService
    前端总结数据结构与算法基础
    node知识点及第三方模块
    消息轮播
    el-date-picker 组件时间格式化方式
    Vue+Element前端导入导出Excel
    vue单元测试
  • 原文地址:https://www.cnblogs.com/VisJiao/p/BZOJ4553.html
Copyright © 2020-2023  润新知