Bzoj4553: Tjoi2016&Heoi2016-序列

5 篇文章 0 订阅
2 篇文章 0 订阅

Description

佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他。
玩具上有一个数列,数列中某些项的值可能会变化,
她想请教你,能否选出一个子序列,使得在任意一种变化中,这个子序列都是不降的?请你告诉她这个子序列的最长长度即可
注意:每种变化最多只有一个值发生变化。
样例输入1中,所有的变化是:

1 2 3
2 2 3
1 3 3
1 1 3
1 2 4

选择子序列为原序列,即在任意一种变化中均为不降子序列
样例输入2中,所有的变化是:

3 3 3
3 2 3

选择子序列为第一个元素和第三个元素,或者第二个元素和第三个元素,均可满足要求

Input

输入的第一行有两个正整数n, m
分别表示序列的长度和变化的个数。
接下来一行有n个数,表示这个数列原始的状态。
接下来m行,每行有2个数x, y,
表示数列的第x( 1xn )项可以变化成y这个值
所有数字均为正整数,且小于等于 105

Output

输出一个整数,表示对应的答案

Sample Input

3 4
1 2 3
1 2
2 3
2 1
3 4

Sample Output

3

首先自然想到对于每一个位置
只有变化的最大值和最小值
对它造成影响
对于位置i,把它们分别记做 MAXi MINi ,i位置的值记做 vi
考虑Dp

f[i]=max(f[j]+1)

0j<i,MAXjvi,vjMINi

可以用二维数据结构优化
也可以CDQ分治
考虑 [l,mid] [mid,r] 的贡献
排一波序然后数据结构维护

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
char ch;
int fl;
inline void read(int &a){
    for(fl=1,ch=getchar();ch<'0'||ch>'9';ch=getchar()) if (ch=='-') fl=-fl;
    for(a=0;ch>='0'&&ch<='9';ch=getchar()) a=(a<<3)+(a<<1)+(ch^'0');
    a*=fl;
}
const int Maxn=1e5+10;
struct Ques{
    int x,y,id;
    bool operator <(const Ques &A)const{return x!=A.x?x<A.x:id<A.id;} 
}G[Maxn]; 
int c[Maxn],MAXN[Maxn],MINN[Maxn],Val[Maxn],F[Maxn];
inline void Add(int x,int v){for(int i=x;i<=Maxn;i+=i&(-i)) c[i]=max(c[i],v);}
inline void Clear(int x){for(int i=x;i<=Maxn;i+=i&(-i)) c[i]=0;}
inline int Qry(int x){ int Ans=0;for(int i=x;i;i-=i&(-i)) Ans=max(Ans,c[i]);return Ans;}
void CDQ(int l,int r){
    int mid=(l+r)>>1;
    if(l==r){F[mid]=max(F[mid],1);return;}
    CDQ(l,mid);
    for(int i=l;i<=r;i++)G[i].id=i;
    for(int i=l;i<=mid;i++)G[i].x=MAXN[i],G[i].y=Val[i];
    for(int i=mid+1;i<=r;i++)G[i].x=Val[i],G[i].y=MINN[i];
    sort(G+l,G+r+1);
    for(int i=l;i<=r;i++){
        if (G[i].id<=mid) Add(G[i].y,F[G[i].id]);
        else F[G[i].id]=max(F[G[i].id],Qry(G[i].y)+1);
    }
    for(int i=l;i<=r;i++)
    if (G[i].id<=mid)Clear(G[i].y);
    CDQ(mid+1,r);
}
int main(){
    int n,m,i,Ans=0,x,y;
    read(n);read(m);
    for(i=1;i<=n;i++)read(Val[i]),MAXN[i]=MINN[i]=Val[i];
    for(i=1;i<=m;i++){
        read(x);read(y);
        MAXN[x]=max(MAXN[x],y);MINN[x]=min(MINN[x],y);
    }
    CDQ(1,n);
    for(i=1;i<=n;i++)Ans=max(Ans,F[i]);
    printf("%d",Ans);
    return 0;
}

Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值