codeforces 650D (樹狀陣列)
阿新 • • 發佈:2019-01-09
題意:動態LIS,改變一個值求LIS。
先把詢問離線下來按照改變的位置排序,把所有的數字離散化。首先先用樹狀陣列求出每一位為結尾的最長上升字首f[i]和每一位開始的最長上升字尾g[i],然後考慮每一個數字改變後的LIS情況,分成兩種討論:
LIS不包含這個數。這種情況比較簡單,考慮是不是每一個LIS都含有這個數字即可,也即對於所有的LIS,某一位必須是這個數。所以直接統計每一個數字在LIS中的位置,然後判斷這個位置是否唯一即可。
LIS包含這個數。對於一個數a[i],顯然需要找到一個j和k使得
aj<ai<ak並且i<j<k ,直接正反掃兩遍用樹狀陣列統計即可。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <cmath>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#pragma comment(linker, "/STACK:102400000,102400000")
#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;
add1 (a[i], f[i]);
}
Clear (c, 0);
for (int i = n; i >= 1; i--) {
g[i] = query2 (a[i]+1)+1;
add2 (a[i], g[i]);
}
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) {
add1 (a[pos], f[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) {
add2 (a[pos], g[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
*/