[Tjoi2016&Heoi2016]序列
来源:互联网 发布:淘宝服务中心首页 编辑:程序博客网 时间:2024/06/07 21:16
Description
佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他。玩具上有一个数列,数列中某些项的值可能会变化,但同一个时刻最多只有一个值发生变化。现在佳媛姐姐已经研究出了所有变化的可能性,她想请教你,能否选出一个子序列,使得在任意一种变化中,这个子序列都是不降的?请你告诉她这个子序列的最长长度即可
。注意:每种变化最多只有一个值发生变化。在样例输入1中,所有的变化是:
1 2 3
2 2 3
1 3 3
1 1 31 2 4
选择子序列为原序列,即在任意一种变化中均为不降子序列在样例输入2中,所有的变化是:3 3 33 2 3选择子序列
为第一个元素和第三个元素,或者第二个元素和第三个元素,均可满足要求
Input
输入的第一行有两个正整数n, m,分别表示序列的长度和变化的个数。接下来一行有n个数,表示这个数列原始的状态。接下来m行,每行有2个数x, y,表示数列的第x项可以变化成y这个值。1 <= x <= n。所有数字均为正整数,且小于等于100,000
Output
输出一个整数,表示对应的答案
Sample Input
3 4
1 2 3
1 2
2 3
2 1
3 4
Sample Output
3
分析
设f[i]表示以i为最后一位,能求出的序列最长为多少。
f[i]=max{f[j]+1} 一个可以转移的j要满足以下条件:
1. j< i
2. a[j]< a[i] (两个都不变化)
3. a[j]< Min[i] (i变化,Min[i]为i可变化的最小值)
4. Max[j]< a[i] (j变化,Max[j]为j可变化的最大值)
时间复杂度
正解1
其实可以把条件2、3、4合并一下,然后变成max(a[j],Max[j])< a[i] 和a[j]< min(a[i],Min[i])两个条件
两个条件,很容易让人想到用树套树做。
时间复杂度
正解2
也是上面的两个条件。
枚举更新f[i]时,可以把它拆成两个操作:查询最大值和插入操作。
操作是相互独立的,而且可以离线做,所以可以考虑cdq分治
对于操作区间[l,r],先处理完[l,mid],然后用这部分的答案更新[mid+1,r]的答案,最后递归处理[mid+1,r]。离线更新答案可以按一个条件排序,然后用树状数组查询。
时间复杂度
cdq分治的代码#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn=200005,N=100000;int n,m,tot,a[maxn],b[maxn],c[maxn],f[maxn],s[maxn];struct data{ int x,y,v;}A[maxn],B[maxn];bool cmp(data a,data b){ return a.x<b.x;}int lowbit(int x){ return x & (-x);}void insert(int x,int y){ for (;x<=N;x+=lowbit(x)) s[x]=max(s[x],y);}int get(int x){ int k=0; for (;x;x-=lowbit(x)) k=max(k,s[x]); return k;}void clear(int x){ for (;x<=N;x+=lowbit(x)) s[x]=0;}void solve(int l,int r){ if (l==r) { f[l]=max(f[l],1); return; } int mid=(l+r)/2,i,j; solve(l,mid); for (i=l;i<=mid;i++) { A[i].v=f[i]; A[i].x=a[i]; A[i].y=c[i]; } for (i=mid+1;i<=r;i++) { B[i].v=i; B[i].x=b[i]; B[i].y=a[i]; } sort(A+l,A+mid+1,cmp); sort(B+mid+1,B+r+1,cmp); for (i=l,j=mid+1;j<=r;j++) { for (;i<=mid && A[i].x<=B[j].x;i++) insert(A[i].y,A[i].v); f[B[j].v]=max(f[B[j].v],get(B[j].y)+1); } for (i--;i>=l;i--) clear(A[i].y); solve(mid+1,r);}int main(){ scanf("%d%d",&n,&m); memset(b,42,sizeof(b)); for (int i=1;i<=n;i++) scanf("%d",&a[i]); while (m--) { int x,y; scanf("%d%d",&x,&y); b[x]=min(b[x],y); c[x]=max(c[x],y); } for (int i=1;i<=n;i++) { b[i]=min(b[i],a[i]); c[i]=max(c[i],a[i]); } solve(1,n); int ans=0; for (int i=1;i<=n;i++) ans=max(ans,f[i]); printf("%d\n",ans); return 0;}
- BZOJ4553 [Tjoi2016&Heoi2016]序列
- bzoj4553【TJOI2016&HEOI2016】序列
- [Tjoi2016&Heoi2016]序列
- 【TJOI2016&&HEOI2016】序列
- 4553: [Tjoi2016&Heoi2016]序列
- 4553: [Tjoi2016&Heoi2016]序列
- BZOJ4553: [Tjoi2016&Heoi2016]序列
- 【bzoj4553】[Tjoi2016&Heoi2016]序列
- Bzoj4553: Tjoi2016&Heoi2016-序列
- bzoj 4553: [Tjoi2016&Heoi2016]序列
- BZOJ 4553: [Tjoi2016&Heoi2016]序列
- BZOJ 4553 [Tjoi2016&Heoi2016]序列
- BZOJ 4553: [Tjoi2016&Heoi2016]序列
- [Tjoi2016&Heoi2016]【BZOJ 4553】【JZOJ 4606】序列
- 【50.40%】【BZOJ 4553】[Tjoi2016&Heoi2016]序列
- [BZOJ4553][Tjoi2016&Heoi2016]序列 CDQ分治
- [bzoj4553][Tjoi2016&Heoi2016]序列 cdq分治
- 【bzoj4553】【TJOI2016&HEOI2016】【序列】【cdq分治+树状数组】
- Mysql数据库语句大全
- Apache OpenSSL生成证书使用
- 正则表达式语法查询
- ebs OAF Pages edit / remove / hide
- mysql 索引的使用
- [Tjoi2016&Heoi2016]序列
- ASP.NET的内置对象之三 Session
- 1.容器
- c++的四种强制转换
- 谈谈事件分发
- QML中定义私有变量
- ora-01178及ORA-01511错误
- Tkinter教程之Toplevel篇
- 图像质量评价的两个方法