BZOJ 4553 [Tjoi2016&Heoi2016]序列 ——CDQ分治 树状数组
考虑答案的构成,发现是一个有限制条件的偏序问题。
然后三个维度的DP,可以排序、CDQ、树状数组各解决一维。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | #include <map> #include <cmath> #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i>=k;--i) #define ll long long #define mp make_pair #define maxn 200005 struct node{ int a,b,c,id,ans; void print() {printf( "ID is %d Upper %d Middle %d Lower %d\n" ,c,b,a);} }q[maxn]; int n,m; bool cmp1(node x,node y){ return x.b<y.b;} bool cmp2(node x,node y){ return x.a<y.a;} bool cmp3(node x,node y){ return x.id<y.id;} int bit[maxn]; void add( int x, int f) { for (;x<maxn;x+=x&(-x)) bit[x]=max(bit[x],f); } void del( int x) { for (;x<maxn;x+=x&(-x)) bit[x]=0; } int query( int x) { int ret=0; for (;x;x-=x&(-x)) ret=max(ret,bit[x]); return ret; } void CDQ( int l, int r) { if (l==r) return ; int mid=l+r>>1; sort(q+l,q+r+1,cmp3); CDQ(l,mid); sort(q+l,q+mid+1,cmp1); sort(q+mid+1,q+r+1,cmp2); int now=l; F(i,mid+1,r) { while (now<=mid&&q[now].b<=q[i].a) add(q[now].c,q[now].ans),now++; q[i].ans=max(q[i].ans,query(q[i].b)+1); } F(i,l,now-1) del(q[i].c); CDQ(mid+1,r); } int main() { scanf( "%d%d" ,&n,&m); F(i,1,n) { scanf( "%d" ,&q[i].b); q[i].a=q[i].c=q[i].b; q[i].id=i; q[i].ans=1; } F(i,1,m) { int x,y; scanf( "%d%d" ,&x,&y); q[x].a=min(q[x].a,y); q[x].c=max(q[x].c,y); } CDQ(1,n); int ans=0; F(i,1,n) ans=max(ans,q[i].ans); printf( "%d\n" ,ans); } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步