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
 
设B[i]表示A[i]能变成的最大值,C[i]表示A[i]能变成的最小值,然后就可以DP了。
f[i]=max(f[j]|B[j]<=A[i]&&A[j]<=C[i])+1,不难发现是一个三维偏序结构。
首先我写了个线段树套线段树,然后被精妙地卡内存了。
#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
if(head==tail) {
int l=fread(buffer,1,BufferSize,stdin);
tail=(head=buffer)+l;
}
return *head++;
}
inline int read() {
int x=0,f=1;char c=Getchar();
for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=100010;
const int maxnode=13000010;
const int inf=1e9;
int n,m,ans,A[maxn],B[maxn],C[maxn],f[maxn];
int root[maxn<<2],maxv[maxnode],ls[maxnode],rs[maxnode],ToT;
void insert(int& o,int l,int r,int p,int val) {
if(!o) o=++ToT;maxv[o]=max(maxv[o],val);
if(l==r) return;int mid=l+r>>1;
if(p<=mid) insert(ls[o],l,mid,p,val);
else insert(rs[o],mid+1,r,p,val);
}
void insert(int o,int l,int r,int x,int y,int val) {
insert(root[o],1,100000,y,val);if(l==r) return;
int mid=l+r>>1,lc=o<<1,rc=lc|1;
if(x<=mid) insert(lc,l,mid,x,y,val);
else insert(rc,mid+1,r,x,y,val);
}
int query(int o,int l,int r,int p) {
if(!o) return 0;
if(l==r) return maxv[o];
int mid=l+r>>1;
if(p<=mid) return query(ls[o],l,mid,p);
return max(maxv[ls[o]],query(rs[o],mid+1,r,p));
}
int query(int o,int l,int r,int x,int y) {
if(l==r) return query(root[o],1,100000,y);
int mid=l+r>>1,lc=o<<1,rc=lc|1;
if(x<=mid) return query(lc,l,mid,x,y);
return max(query(root[lc],1,100000,y),query(rc,mid+1,r,x,y));
}
int main() {
n=read();m=read();
rep(i,1,n) A[i]=B[i]=C[i]=read();
rep(i,1,m) {
int x=read(),y=read();
B[x]=max(B[x],y);
C[x]=min(C[x],y);
}
rep(i,1,n) {
f[i]=query(1,1,100000,A[i],C[i])+1;
insert(1,1,100000,B[i],A[i],f[i]);
ans=max(ans,f[i]);
}
printf("%d\n",ans);
return 0;
}

然后写了个kd树,跑得真是慢。。。

#include<cstdio>
#include<cctype>
#include<set>
#include<cstring>
#include<algorithm>
#define L T[o].lc
#define R T[o].rc
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
if(head==tail) {
int l=fread(buffer,1,BufferSize,stdin);
tail=(head=buffer)+l;
}
return *head++;
}
inline int read() {
int x=0,f=1;char c=Getchar();
for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=100010;
const int inf=1e9;
int D,n,m,ans,A[maxn],B[maxn],C[maxn],f[maxn];
struct Node {
int x[2],mx[2],mn[2],lc,rc,val,maxv;
bool operator < (const Node& ths) const {return x[D]<ths.x[D]||(x[D]==ths.x[D]&&x[D^1]<ths.x[D^1]);}
}T[maxn],P;
void maintain(int o) {T[o].maxv=max(T[o].val,max(T[L].maxv,T[R].maxv));}
void build(int& o,int l,int r,int cur) {
int mid=l+r>>1;D=cur;o=mid;nth_element(T+l,T+mid,T+r+1);
if(l<mid) build(L,l,mid-1,cur^1);
if(mid<r) build(R,mid+1,r,cur^1);
rep(c,0,1) {
T[o].mn[c]=min(T[o].x[c],min(T[L].mn[c],T[R].mn[c]));
T[o].mx[c]=max(T[o].x[c],max(T[L].mx[c],T[R].mx[c]));
}
}
int query(int o) {
if(!o) return 0;
if(T[o].mn[0]>P.x[0]||T[o].mn[1]>P.x[1]) return 0;
if(T[o].mx[0]<=P.x[0]&&T[o].mx[1]<=P.x[1]) return T[o].maxv;
int ans=0;
if(T[o].x[0]<=P.x[0]&&T[o].x[1]<=P.x[1]) ans=T[o].val;
return max(ans,max(query(L),query(R)));
}
void insert(int o,int cur,int val) {
if(T[o].x[0]==P.x[0]&&T[o].x[1]==P.x[1]) T[o].val=max(T[o].val,val);
else {
D=cur;insert(P<T[o]?L:R,cur^1,val);
}
maintain(o);
}
int main() {
T[0].mn[0]=T[0].mn[1]=inf;
T[0].mx[0]=T[0].mx[1]=-inf;
n=read();m=read();int rt=0;
rep(i,1,n) A[i]=B[i]=C[i]=read();
rep(i,1,m) {
int x=read(),y=read();
B[x]=max(B[x],y);
C[x]=min(C[x],y);
}
rep(i,1,n) T[i].x[0]=B[i],T[i].x[1]=A[i];
build(rt,1,n,0);
rep(i,1,n) {
P.x[0]=A[i];P.x[1]=C[i];
f[i]=query(rt)+1;
P.x[0]=B[i];P.x[1]=A[i];
insert(rt,0,f[i]);
ans=max(ans,f[i]);
}
printf("%d\n",ans);
return 0;
}

  

BZOJ4553: [Tjoi2016&Heoi2016]序列的更多相关文章

  1. [BZOJ4553][TJOI2016&&HEOI2016]序列(CDQ分治)

    4553: [Tjoi2016&Heoi2016]序列 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1202  Solved: 554[Su ...

  2. [BZOJ4553][Tjoi2016&Heoi2016]序列 cdp分治+dp

    4553: [Tjoi2016&Heoi2016]序列 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 260  Solved: 133[Sub ...

  3. bzoj4553 [Tjoi2016&Heoi2016]序列 树状数组(区间最大值)+cqd

    [Tjoi2016&Heoi2016]序列 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1006  Solved: 464[Submit][ ...

  4. BZOJ4553: [Tjoi2016&Heoi2016]序列 树套树优化DP

    把pos[i]上出现的平常值定义为nor[i]最大值定义为max[i]最小值定义为min[i],那么我们发现在两个值,i(前),j(后),当且仅当max[i]<=nor[j],nor[i]< ...

  5. 【BZOJ4553】[Tjoi2016&Heoi2016]序列 cdq分治+树状数组

    [BZOJ4553][Tjoi2016&Heoi2016]序列 Description 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值可能 ...

  6. BZOJ 4553 Tjoi2016&Heoi2016 序列

    Tjoi2016&Heoi2016序列 Description 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值 可能会变化,但同一个时刻最 ...

  7. 4553: [Tjoi2016&Heoi2016]序列

    4553: [Tjoi2016&Heoi2016]序列 链接 分析: 注意所有m此操作中,只会发生一个,于是考虑dp.dp[i]=dp[j]+1,j<i,a[j]<=L[i],R[ ...

  8. 【50.40%】【BZOJ 4553】[Tjoi2016&Heoi2016]序列

    Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 371  Solved: 187 [Submit][Status][Discuss] Descript ...

  9. BZOJ 4553 [Tjoi2016&Heoi2016]序列 ——CDQ分治 树状数组

    考虑答案的构成,发现是一个有限制条件的偏序问题. 然后三个维度的DP,可以排序.CDQ.树状数组各解决一维. #include <map> #include <cmath> # ...

随机推荐

  1. [Linux][VMWare] 学习笔记之安装Linux系统-网络配置

    最近开始折腾Linux,在本机装了个VMWare和Centos,装完之后虚拟机里面的OS可以上网,但是使用SecureCRT连接不上虚拟机,开始折腾这个网络. vmware安装好以后,会自动添加两张网 ...

  2. Zero Copy 简介

    转自:http://blog.csdn.net/zzz_781111/article/details/7534649 许多web应用都会向用户提供大量的静态内容,这意味着有很多data从硬盘读出之后, ...

  3. C语言中如何将二维数组作为函数的参数传递

    今天写程序的时候要用到二维数组作参数传给一个函数,我发现将二维数组作参数进行传递还不是想象得那么简单里,但是最后我也解决了遇到的问题,所以这篇文章主要介绍如何处理二维数组当作参数传递的情况,希望大家不 ...

  4. How to use the Visual Studio

    推荐一个提供VS配色方案的一个网站:StudioStyles,域名和网站同名:http://studiostyl.es/ 2. 整行剪切:Ctrl + X.光标不要选中任何文字,然后按这个快捷键就可以 ...

  5. Http 请求处理流程

    引言 我查阅过不少Asp.Net的书籍,发现大多数作者都是站在一个比较高的层次上讲解Asp.Net.他们耐心.细致地告诉你如何一步步拖放控件.设置控件属性.编写CodeBehind代码,以实现某个特定 ...

  6. 汇编学习(四)——算术运算程序

    (一)跳转指令 一.无条件跳转指令(不管标志寄存器,执行到这句直接跳转) 1.段内直接跳转指令 (1)指令格式: JMP SHORT short_label; IP<--IP+DB,即代码直接跳 ...

  7. Action处理请求参数

    第一种 :Action 本身作为model对象,通过成员setter封装 (属性驱动 ) 第一种方式:<br> <form action="${pageContext.re ...

  8. URL编码表%20Base64编码表%20HTTP消息含义

    URL编码表 backspace 8% A 41% a 61% § %A7 Õ %D5   tab 9% B 42% b 62% « %AB Ö %D6   linefeed %0A C 43% c ...

  9. sqoop中,如果数据中本身有换行符,会导致数据错位

    sqoop中,如果数据中本身有换行符,会导致数据错位: 解决办法: 在sqoop import时修改配置文件 sudo -u hive sqoop import --connect jdbc:mysq ...

  10. cdh环境下,spark streaming与flume的集成问题总结

    文章发自:http://www.cnblogs.com/hark0623/p/4170156.html  转发请注明 如何做集成,其实特别简单,网上其实就是教程. http://blog.csdn.n ...