# codeforces 650D (树状数组)

## 题目链接：点击这里

• LIS不包含这个数。这种情况比较简单，考虑是不是每一个LIS都含有这个数字即可，也即对于所有的LIS，某一位必须是这个数。所以直接统计每一个数字在LIS中的位置，然后判断这个位置是否唯一即可。

• LIS包含这个数。对于一个数a[i],显然需要找到一个j和k使得aj<ai<aki<j<k$a_j，直接正反扫两遍用树状数组统计即可。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <cmath>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#define Clear(x,y) memset (x,y,sizeof(x))
#define Close() ios::sync_with_stdio(0)
#define Open() freopen ("more.in", "r", stdin)
#define get_min(a,b) a = min (a, b)
#define get_max(a,b) a = max (a, b);
#define y0 yzz
#define y1 yzzz
#define fi first
#define se second
#define pii pair<int, int>
#define pli pair<long long, int>
#define pll pair<long long, long long>
#define pb push_back
#define pl c<<1
#define pr (c<<1)|1
#define lson tree[c].l,tree[c].mid,pl
#define rson tree[c].mid+1,tree[c].r,pr
#define mod 1000000007
typedef unsigned long long ull;
template <class T> inline T lowbit (T x) {return x&(-x);}
template <class T> inline T sqr (T x) {return x*x;}
template <class T>
inline bool scan (T &ret) {
char c;
int sgn;
if (c = getchar(), c == EOF) return 0; //EOF
while (c != '-' && (c < '0' || c > '9') ) c = getchar();
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
const double pi = 3.14159265358979323846264338327950288L;
using namespace std;
#define INF 1e8
#define maxn 800005
#define maxm 1000005
//-----------------morejarphone--------------------//

int n, m, cnt;
vector <int> num;
int a[maxn];
struct Q {
int pos, num, id;
bool operator < (const Q &a) const {
return pos < a.pos;
}
} qu[maxn];
int f[maxn], g[maxn];
int c[maxn];

void add1 (int x, int num) {
for (int i = x; i < maxn; i += lowbit (i)) get_max (c[i], num);
}
int query1 (int x) {
int ans = 0;
for (int i = x; i > 0; i -= lowbit (i)) get_max (ans, c[i]);
return ans;
}
void add2 (int x, int num) {
for (int i = x; i > 0; i -= lowbit (i)) get_max (c[i], num);
}
int query2 (int x) {
int ans = 0;
for (int i = x; i < maxn; i += lowbit (i)) get_max (ans, c[i]);
return ans;
}

int LIS;//LIS的长度
void init () {
Clear (c, 0);
for (int i = 1; i <= n; i++) {
f[i] = query1 (a[i]-1)+1;
}
Clear (c, 0);
for (int i = n; i >= 1; i--) {
g[i] = query2 (a[i]+1)+1;
}
LIS = 0;
for (int i = 1; i <= n; i++) get_max (LIS, f[i]+g[i]-1);
}

void lisanhua () {
sort (num.begin (), num.end ());
num.erase (unique (num.begin (), num.end ()), num.end ());
cnt = num.size ();
for (int i = 1; i <= n; i++)
a[i] = lower_bound (num.begin (), num.end (), a[i])-num.begin ()+1;
for (int i = 1; i <= m; i++)
qu[i].num = lower_bound (num.begin (), num.end (), qu[i].num)-num.begin ()+1;
}

int ans1[maxn];//不包含每一个数的LIS
int tmp[maxn];
void solve1 () {
Clear (tmp, 0);
for (int i = 1; i <= n; i++) if (f[i]+g[i]-1 == LIS) {
tmp[f[i]]++;
}
for (int i = 1; i <= n; i++) {
if (f[i]+g[i]-1 == LIS && tmp[f[i]] == 1) ans1[i] = LIS-1;
else ans1[i] = LIS;
}
}

//包含每一个改变值的LIS
int ans[maxn];//最后的答案
int l[maxn], r[maxn];//左边比他小的最长 右边比他大的最长
void solve2 () {
Clear (c, 0);
int pos = 1;
for (int i = 1; i <= m; i++) {
while (pos < qu[i].pos) {
pos++;
}
l[i] = query1 (qu[i].num-1);
}
Clear (c, 0);
pos = n;
for (int i = m; i >= 1; i--) {
while (pos > qu[i].pos) {
pos--;
}
r[i] = query2 (qu[i].num+1);
}
for (int i = 1; i <= m; i++) {
ans[qu[i].id] = ans1[qu[i].pos];
get_max (ans[qu[i].id], l[i]+r[i]+1);
}
}

int main () {
scanf ("%d%d", &n, &m);
num.clear ();
for (int i = 1; i <= n; i++) {
scan (a[i]);
num.pb (a[i]);
}
for (int i = 1; i <= m; i++) {
scanf ("%d%d", &qu[i].pos, &qu[i].num);
num.pb (qu[i].num);
qu[i].id = i;
}
sort (qu+1, qu+1+m);
lisanhua ();
init ();
solve1 ();
solve2 ();
for (int i = 1; i <= m; i++) {
printf ("%d\n", ans[i]);
}
return 0;
}
/*
15 1
76 9 32 82 40 91 46 5 12 69 44 97 30 13 29
2 62
6 3
7 10 6 9 5 8
1 1
6 9
4 11
*/

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120