Codeforces Round #345 (Div. 1) D. Zip-line LIS 离线 离散化 线段树

来源:互联网 发布:人工智能疾病诊断 编辑:程序博客网 时间:2024/05/21 11:00

题目链接:http://codeforces.com/contest/650/problem/D
题意:
给你n个数,m个询问

每次单点修改,然后问你现在整个序列的lis长度。

修改完之后,要求修改回去。

解法:

询问离线。
我们维护四个东西,dp1[i]表示从1开始到第i个位置的最长上升子序列长度,dp2[i]表示从n开始到第i个位置的最长递减子序列长度。dp3[i]表示第i个询问的那个位置从1开始到第x(即询问的位置)个位置的最长上升子序列长度,dp4[i]表示递减。
假如询问是x,y那么
然后我们判断一下第x个位置是不是lis的关键位置,是的话,ans=lis。否则的话,ans=lis-1。关键位置就是这个位置是全局lis不可替代的一个数。
然后ans = max(ans,dp3[i]+dp4[i]-1)这个很显然……
然后就完了。

//CF 650D#include <bits/stdc++.h>using namespace std;const int maxn = 400050;int n, m, a[maxn], dp1[maxn], dp2[maxn], dp3[maxn], dp4[maxn];///dp1[i]表示从1开始到第i个位置的最长上升子序列长度,dp2[i]表示从n开始到第i个位置的最长递减子序列长度。///dp3[i]表示第i个询问的那个位置从1开始到第x(即询问的位置)个位置的最长上升子序列长度,dp4[i]表示递减。struct Seg{    struct node{        int l, r, maxlen;    }T[maxn*10];    void pushup(int rt){        T[rt].maxlen = max(T[rt*2].maxlen, T[rt*2+1].maxlen);    }    void build(int l, int r, int rt){        T[rt].l = l, T[rt].r = r, T[rt].maxlen = 0;        if(l == r) return;        int mid = (l+r)/2;        build(l, mid, rt*2);        build(mid+1, r, rt*2+1);    }    void update(int pos, int val, int rt){        if(T[rt].l == pos && pos == T[rt].r){            T[rt].maxlen = val;            return;        }        int mid = (T[rt].l + T[rt].r) / 2;        if(pos <= mid) update(pos, val, rt*2);        else update(pos, val, rt*2+1);        pushup(rt);    }    int query(int L, int R, int rt){        if(L <= T[rt].l && T[rt].r <= R){            return T[rt].maxlen;        }        else{            int mid = (T[rt].l + T[rt].r) / 2;            int res = 0;            if(L <= mid) res = max(res, query(L, R, rt*2));            if(mid < R) res = max(res, query(L, R, rt*2+1));            return res;        }    }}L, R;map <int, int> H;vector <int> V;struct node{    int x, y;}Q[maxn];vector <pair<int, int>> q[maxn]; //<idx, num>int cnt[maxn];int main(){    scanf("%d%d", &n, &m);    for(int i = 1; i <= n; i++){        scanf("%d", &a[i]);        V.push_back(a[i]);    }    for(int i = 1; i <= m; i++){        scanf("%d%d", &Q[i].x, &Q[i].y);        V.push_back(Q[i].y);    }    sort(V.begin(), V.end());    V.erase(unique(V.begin(), V.end()), V.end());    for(int i = 0; i < V.size(); i++) H[V[i]] = i+1;    for(int i = 1; i <= n; i++) a[i] = H[a[i]];    for(int i = 1; i <= m; i++){        Q[i].y = H[Q[i].y];        q[Q[i].x].push_back(make_pair(i, Q[i].y));    }    L.build(1, V.size()+5, 1);    for(int i = 1; i <= n; i++){        dp1[i] = L.query(1, a[i]-1, 1) + 1;        for(int j = 0; j < q[i].size(); j++){            int id = q[i][j].first;            int x = q[i][j].second;            dp3[id] = L.query(1, x-1, 1) + 1;        }        L.update(a[i], dp1[i], 1);    }    reverse(a+1, a+n+1);    R.build(1, V.size()+5, 1);    for(int i = 1; i <= n; i++){        dp2[i] = R.query(a[i]+1, V.size(), 1) + 1;        for(int j = 0; j < q[n-i+1].size(); j++){            int id = q[n-i+1][j].first;            int x = q[n-i+1][j].second;            dp4[id] = R.query(x+1, V.size(), 1) + 1;        }        R.update(a[i], dp2[i], 1);    }    int LIS = 0;    for(int i = 1; i <= n; i++){        LIS = max(LIS, dp1[i]);    }    for(int i = 1; i <= n; i++){        if(dp1[i] + dp2[n-i+1] == LIS + 1){            cnt[dp1[i]]++;        }    }    for(int i = 1; i <= m; i++){        int ans = LIS;        int x = Q[i].x;        if(dp1[x] + dp2[n-x+1] == LIS+1 && cnt[dp1[x]] == 1) ans--;        ans = max(ans, dp3[i] + dp4[i] - 1);        printf("%d\n", ans);    }    return 0;}
0 0
原创粉丝点击