4553: [Tjoi2016&Heoi2016]序列
Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 1150 Solved: 527
[Submit][Status][Discuss]
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
题解
(minV[i])表示(i)这个位置出现过的最小值
(maxV[i])表示(i)这个位置出现过的最大值
裸的dp方程:(dp[i] = max(dp[j] + 1), if a[j] <= minV[i], a[i] >= maxV[j])
右边这个东西是个经典的二维数点问题,无穷多的做法
CDQ分治/树套树/.....
线段树套线段树被卡爆空间
卡了半天终于卡过了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <cmath>
#include <sstream>
inline int lowbit(int x){return x & -x;}
inline int max(int a, int b){return a > b ? a : b;}
inline int min(int a, int b){return a < b ? a : b;}
inline void read(int &x)
{
x = 0;char ch = getchar(), c = ch;
while(ch < '0' || ch > '9') c = ch, ch = getchar();
while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
if(c == '-') x = -x;
}
const int INF = 0x3f3f3f3f;
const int MAXN = 160000 + 10;
int n,m,num[MAXN],maxV[MAXN],minV[MAXN],ma;
//X为num Y为maxV
int dp[MAXN], dataY[MAXN << 6], ans, ls[MAXN << 6], rs[MAXN << 6], root[MAXN << 2], tot;
int newnode(){return ++ tot;}
void modifyY(int p, int k, int &o, int l = 1, int r = ma)
{
if(!o) o = newnode();
dataY[o] = max(dataY[o], k);
if(l == r) return;
int mid = (l + r) >> 1;
if(p <= mid) modifyY(p, k, ls[o], l, mid);
else modifyY(p, k, rs[o], mid + 1, r);
return;
}
void modifyX(int x, int y, int k, int o = 1, int l = 1, int r = ma)
{
modifyY(y, k, root[o]);
if(l == r) return;
int mid = (l + r) >> 1;
if(x <= mid) modifyX(x, y, k, o << 1, l, mid);
else modifyX(x, y, k, o << 1 | 1,mid + 1, r);
}
int askY(int y1, int y2, int o, int l = 1, int r = ma)
{
if(!o) return 0;
if(y1 <= l && y2 >= r) return dataY[o];
int mid = (l + r) >> 1, ans = 0;
if(mid >= y1) ans = max(ans, askY(y1, y2, ls[o], l, mid));
if(mid < y2) ans = max(ans, askY(y1, y2, rs[o], mid + 1, r));
return ans;
}
int askX(int x1, int x2, int y1, int y2, int o = 1, int l = 1, int r = ma)
{
if(x1 <= l && x2 >= r) return askY(y1, y2, root[o]);
int mid = (l + r) >> 1, ans = 0;
if(mid >= x1) ans = max(ans, askX(x1, x2, y1, y2, o << 1, l, mid));
if(mid < x2) ans = max(ans, askX(x1, x2, y1, y2, o << 1 | 1, mid + 1, r));
return ans;
}
void modify(int x)
{
modifyX(maxV[x], num[x], dp[x]);
}
int ask(int x)
{
return askX(1, num[x], 1, minV[x]);
}
int main()
{
read(n), read(m);
for(int i = 1;i <= n;++ i) read(num[i]), maxV[i] = minV[i] = num[i], ma = max(ma, num[i]);
for(int i = 1;i <= m;++ i)
{
int tmp1,tmp2;
read(tmp1), read(tmp2);
maxV[tmp1] = max(maxV[tmp1], tmp2);
minV[tmp1] = min(minV[tmp1], tmp2);
ma = max(ma, tmp2);
}
for(int i = 1;i <= n;++ i)
dp[i] = ask(i) + 1, modify(i), ans = max(ans, dp[i]);
printf("%d", ans);
return 0;
}