• codeforces 650D. Zip-line 线段树


    题目链接

    题目的意思很简单, 就是给你n个数, m个询问, 每次询问修改某一个位置的值, 然后问你修改完之后数列的lis是多少。 询问独立。

    对于原数列, 我们将它离散化, 令dp1[i]为以i为结尾位置的最长上升子序列的长度, dp[2]为以i结尾的从后往前的最长下降子序列的长度。

    原数列的lis显然为max(dp1[i]+dp2[i]-1)。

    然后我们求出哪些位置是关键位置, 所谓关键位置, 就是说如果把这个位置的值改变, 那么lis的值也许就会减1。  求关键位置的方法看代码。

     然后对于每个询问, 令x[i]为位置, y[i]为修改后并离散化的值,我们令dp3[i]表示将x[i]位置修改为y[i]之后, 以x[i]结尾的最长上升子序列的长度, dp4[i]为最长下降的长度。

    那么对于每次询问, 如果x[i]是关键节点, ans[i] = max(lis-1, dp3[i]+dp4[i]-1), 否则的话, ans[i] = max(lis, dp3[i]+dp4[i]-1)。

    具体的可以看代码。

    还有一点要注意的是数组不能开成4e5, 要开成8e5。

    #include <iostream>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <map>
    #include <set>
    #include <string>
    #include <queue>
    #include <stack>
    #include <bitset>
    using namespace std;
    #define pb(x) push_back(x)
    #define ll long long
    #define mk(x, y) make_pair(x, y)
    #define lson l, m, rt<<1
    #define mem(a) memset(a, 0, sizeof(a))
    #define rson m+1, r, rt<<1|1
    #define mem1(a) memset(a, -1, sizeof(a))
    #define mem2(a) memset(a, 0x3f, sizeof(a))
    #define rep(i, n, a) for(int i = a; i<n; i++)
    #define fi first
    #define se second
    typedef pair<int, int> pll;
    const double PI = acos(-1.0);
    const double eps = 1e-8;
    const int mod = 1e9+7;
    const int inf = 1061109567;
    const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
    const int maxn = 8e5+5;
    int sum[maxn<<2], num[maxn], dp1[maxn], dp2[maxn], dp3[maxn], dp4[maxn], a[maxn], b[maxn];
    int x[maxn], y[maxn], ans[maxn];
    vector <pll> v[maxn];
    void update(int p, int val, int l, int r, int rt) {
        if(l == r) {
            sum[rt] = max(sum[rt], val);
            return ;
        }
        int m = l+r>>1;
        if(p<=m)
            update(p, val, lson);
        else
            update(p, val, rson);
        sum[rt] = max(sum[rt<<1],sum[rt<<1|1]);
    }
    int query(int L, int R, int l, int r, int rt) {
        if(L>R)
            return 0;
        if(L<=l&&R>=r) {
            return sum[rt];
        }
        int m = l+r>>1, ret = 0;
        if(L<=m)
            ret = query(L, R, lson);
        if(R>m)
            ret = max(ret, query(L, R, rson));
        return ret;
    }
    int main()
    {
        int n, m, cnt = 0;
        cin>>n>>m;
        for(int i = 1; i<=n; i++) {
            scanf("%d", &a[i]);
            b[cnt++] = a[i];
        }
        for(int i = 0; i<m; i++) {
            scanf("%d%d", &x[i], &y[i]);
            b[cnt++] = y[i];
            v[x[i]].pb(mk(i, y[i]));
        }
        sort(b, b+cnt);
        cnt = unique(b, b+cnt)-b;
        for(int i = 1; i<=n; i++) {
            a[i] = lower_bound(b, b+cnt, a[i])-b+1;
        }
        for(int i = 1; i<=n; i++) {
            dp1[i] = query(1, a[i]-1, 1, cnt, 1)+1;
            for(int j = 0; j<v[i].size(); j++) {
                int tmp = v[i][j].fi;
                int tmpy = lower_bound(b, b+cnt, v[i][j].se)-b+1;
                dp3[tmp] = query(1, tmpy-1, 1, cnt, 1)+1;
            }
            update(a[i], dp1[i], 1, cnt, 1);
        }
        mem(sum);
        for(int i = n; i>=1; i--) {
            dp2[i] = query(a[i]+1, cnt, 1, cnt, 1)+1;
            for(int j = 0; j<v[i].size(); j++) {
                int tmp = v[i][j].fi;
                int tmpy = lower_bound(b, b+cnt, v[i][j].se)-b+1;
                dp4[tmp] = query(tmpy+1, cnt, 1, cnt, 1)+1;
            }
            update(a[i], dp2[i], 1, cnt, 1);
        }
        int maxx = 0;
        for(int i = 1; i<=n; i++) {
            maxx = max(dp1[i]+dp2[i]-1, maxx);      //求原数列lis
        }
        for(int i = 1; i<=n; i++) {
            if(dp1[i]+dp2[i]-1 == maxx) {
                num[dp1[i]]++;              //如果num[dp1[i]] == 1, 那么它就是关键节点
            }
        }
        for(int i = 0; i<m; i++) {
            int tmp = maxx;
            if(dp1[x[i]]+dp2[x[i]]-1 == maxx && num[dp1[x[i]]] == 1) {
                tmp--;
            }
            tmp = max(tmp, dp3[i]+dp4[i]-1);
            ans[i] = tmp;
        }
        for(int i = 0; i<m; i++) {
            printf("%d
    ", ans[i]);
        }
        return 0;
    }
  • 相关阅读:
    《objective-c基础教程》学习笔记(三)—— 从结构体到面向对象
    《objective-c基础教程》学习笔记(二)—— for循环的基本应用
    《objective-c基础教程》学习笔记 (一)—— 开发环境配置和简单类型输出
    asp.net mvc 3.0 知识点整理 ----- (4).asp.net mvc 3 和asp.net mvc 4 对比
    git简单使用(上篇)
    git简单使用(下篇)
    Spring核心概念之Ioc
    "注解"的用法
    struts2进阶篇(3)
    struts2进阶篇(2)
  • 原文地址:https://www.cnblogs.com/yohaha/p/5256797.html
Copyright © 2020-2023  润新知