「luogu4093」[HEOI2016/TJOI2016]序列

写出dp方程,可以发现转移要满足一个三维偏序,那么可以处理三维偏序的方法优化。

CDQ分治:

  cdq分治和树状数组是好伙伴~

  注意分治的顺序,要保证先求解出所有前驱状态。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=100010;
 4 int n,m,dp[N],maxn;
 5 struct Node{
 6     int a,maxv,minv,id;
 7 }node[N];
 8 int cmpa(const Node& x,const Node& y){return x.a<y.a;}
 9 int cmpv(const Node& x,const Node& y){return x.maxv<y.maxv;}
10 int cmpid(const Node& x,const Node& y){return x.id<y.id;}
11 int bit[N];
12 inline int lowbit(int k){return k&(-k);}
13 inline void change(int k,int x){while(k<=maxn) bit[k]=max(bit[k],x),k+=lowbit(k);return;}
14 inline int que(int k){
15     int ans=0;
16     while(k) ans=max(bit[k],ans),k-=lowbit(k);
17     return ans;
18 }
19 inline void reset(int k){
20     while(k<=maxn){
21         if(!bit[k]) return;
22         bit[k]=0,k+=lowbit(k);
23     }
24     return;
25 }
26 void cdq(int l,int r){
27     if(l>=r) return;
28     int mid=(l+r)>>1;
29     cdq(l,mid);
30     sort(node+l,node+mid+1,cmpv);sort(node+mid+1,node+r+1,cmpa);
31     int pl=l,pr=mid+1;
32     while(pl<=mid&&pr<=r){
33         if(node[pl].maxv<=node[pr].a){
34             change(node[pl].a,dp[node[pl].id]);
35             pl++;
36         }else{
37             dp[node[pr].id]=max(dp[node[pr].id],que(node[pr].minv)+1);
38             pr++;
39         }
40     }
41     while(pr<=r){
42         dp[node[pr].id]=max(dp[node[pr].id],que(node[pr].minv)+1);
43         pr++;
44     }
45     for(int i=l;i<=mid;i++) reset(node[i].a);
46     sort(node+l,node+r+1,cmpid);
47     cdq(mid+1,r);
48     return;
49 }
50 int main(){
51     int t1,t2;
52     scanf("%d%d",&n,&m);
53     for(int i=1;i<=n;i++) scanf("%d",&node[i].a),node[i].maxv=node[i].minv=node[i].a,node[i].id=i,dp[i]=1,maxn=max(maxn,node[i].a);
54     while(m--){
55         scanf("%d%d",&t1,&t2);
56         maxn=max(maxn,t2);
57         node[t1].maxv=max(node[t1].maxv,t2);
58         node[t1].minv=min(node[t1].minv,t2);
59     }
60     cdq(1,n);
61     int ans=0;
62     for(int i=1;i<=n;i++) ans=max(ans,dp[i]);
63     printf("%d",ans);
64     return 0;
65 }

树套树:

原文地址:https://www.cnblogs.com/mycups/p/8546976.html

时间: 2024-10-09 04:15:39

「luogu4093」[HEOI2016/TJOI2016]序列的相关文章

luogu4093 [HEOI2016/TJOI2016]序列

因为一个变化只会变化一个值,所以 \(dp[i]=max(dp[j])+1,j<i,maxval_j \leq a[i], a[j] \leq minval_i\) 发现跟二维数点问题挺像,树状数组套线段树爽一爽. #include <iostream> #include <cstdio> using namespace std; int n, m, zdz[100005], zxz[100005], a[100005], uu, vv, cnt, dp[100005], a

洛谷P4093 [HEOI2016/TJOI2016]序列

题目描述 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值可能会变化,但同一个时刻最多只有一个值发生变化.现在佳媛姐姐已经研究出了所有变化的可能性,她想请教你,能否选出一个子序列,使得在任意一种变化中,这个子序列都是不降的?请你告诉她这个子序列的最长长度即可 . 注意:每种变化最多只有一个值发生变化.在样例输入1中,所有的变化是: 1 2 3 2 2 3 1 3 3 1 1 3 1 2 4 选择子序列为原序列,即在任意一种变化中均为不降子序列在

洛谷 P4093 [HEOI2016/TJOI2016]序列

题目描述 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值可能会变化,但同一个时刻最多只有一个值发生变化.现在佳媛姐姐已经研究出了所有变化的可能性,她想请教你,能否选出一个子序列,使得在任意一种变化中,这个子序列都是不降的?请你告诉她这个子序列的最长长度即可 . 注意:每种变化最多只有一个值发生变化.在样例输入1中,所有的变化是: 1 2 3 2 2 3 1 3 3 1 1 3 1 2 4 选择子序列为原序列,即在任意一种变化中均为不降子序列在

【[HEOI2016/TJOI2016]序列】

压行真漂亮 首先这肯定是一个\(dp\)了 设\(dp_i\)表示\(i\)结尾的最长不下降子序列的长度 显然我们要找一个\(j\)来转移 也就是\(dp_i=max(dp_j+1)\) 那么什么样的\(j\)满足条件呢 首先得是\(j<i\) 我们还注意到一个条件就是这个序列里最多也只有一个位置会发生变化 可能是\(i\)这个位置发生变化,那么显然需要满足对于任意的\(a_i\)都需要满足大于等于\(val_j\) 于是就有\(val_j<=min_i\) 自然也有可能是前面的\(j\)发生

题解 P4093 【[HEOI2016/TJOI2016]序列】

这道题原来很水的? noteskey 一开始以为是顺序的 m 个修改,然后选出一段最长子序列使得每次修改后都满足不降 这 TM 根本不可做啊! 于是就去看题解了,然后看到转移要满足的条件的我发出了黑人问号... 然后才发现原来是求的子序列是满足任意一次修改后不降... 于是列出两(san)个条件式子,就可以 CDQ 切掉了 QWQ \(j<i\) \(a_j<min_i\) \(max_j<a_i\) 这里的 max 和 min 就是某个位置上出现过的最 大/小 值 watch out

[HEOI2016/TJOI2016]序列 CDQ分治

---题面--- 题解: 首先我们观察一下,如果一个点对(j, i), 要符合题中要求要满足哪些条件? 首先我们设 j < i 那么有: j < i max[j] < v[i] v[j] < min[i] (注意下面两个式子都是用的v[i],v[j],,,而不是i , j...之前因为这个问题纠结了很久,其实我也不知道我在纠结什么...) 这三个式子是不是很眼熟? 如果式子变成: j < i max[j] < max[i] min[j] < min[i] 是不是就

# [HEOI2016/TJOI2016]序列

题目链接 戳这 Solution 首先考虑最暴力的dp 我们设: \(f[i]\)表示选择\(i\)以后所能形成的满足条件的子序列的最大值 \(minx[i]\)表示\(i\)能转换为的最小值 \(maxx[i]\)表示\(i\)能转换为的最大值 于是转移的条件显然了: \(i>j\) \(minx[i]>=a[j]\) \(a[i]>=maxx[i]\) 对于暴力直接枚举j转移就好了,但却只有50分,想想正解. 条件很明显是三维偏序问题啊.我们可以随便用一些数据结构: 如: cdq分治

AC日记——「SDOI2017」序列计数 LibreOJ 2002

「SDOI2017」序列计数 思路: 矩阵快速幂: 代码: #include <bits/stdc++.h> using namespace std; #define mod 20170408 #define ll long long struct MatrixType { int n,m; ll ai[105][105]; void mem(int n_,int m_) { n=n_,m=m_; for(int i=0;i<=n;i++) for(int v=0;v<=m;v++

LibreOJ #2002. 「SDOI2017」序列计数

二次联通门 : LibreOJ #2002. 「SDOI2017」序列计数 /* LibreOJ #2002. 「SDOI2017」序列计数 线性筛 + 矩阵优化dp 先构造出全部情况的矩阵 用矩阵快速幂计算答案 再构造出全不是质数的矩阵 计算出答案 前一个答案减后一个答案即可 */ #include <cstdio> #include <iostream> #include <cstring> const int BUF = 12312312; char Buf[BU