zoukankan      html  css  js  c++  java
  • Codeforces Round #345 (Div. 1) D. Zip-line 上升子序列 离线 离散化 线段树

    D. Zip-line

    题目连接:

    http://www.codeforces.com/contest/650/problem/D

    Description

    Vasya has decided to build a zip-line on trees of a nearby forest. He wants the line to be as long as possible but he doesn't remember exactly the heights of all trees in the forest. He is sure that he remembers correct heights of all trees except, possibly, one of them.

    It is known that the forest consists of n trees staying in a row numbered from left to right with integers from 1 to n. According to Vasya, the height of the i-th tree is equal to hi. The zip-line of length k should hang over k (1 ≤ k ≤ n) trees i1, i2, ..., ik (i1 < i2 < ... < ik) such that their heights form an increasing sequence, that is hi1 < hi2 < ... < hik.

    Petya had been in this forest together with Vasya, and he now has q assumptions about the mistake in Vasya's sequence h. His i-th assumption consists of two integers ai and bi indicating that, according to Petya, the height of the tree numbered ai is actually equal to bi. Note that Petya's assumptions are independent from each other.

    Your task is to find the maximum length of a zip-line that can be built over the trees under each of the q assumptions.

    In this problem the length of a zip line is considered equal to the number of trees that form this zip-line.

    Input

    The first line of the input contains two integers n and m (1 ≤ n, m ≤ 400 000) — the number of the trees in the forest and the number of Petya's assumptions, respectively.

    The following line contains n integers hi (1 ≤ hi ≤ 109) — the heights of trees according to Vasya.

    Each of the following m lines contains two integers ai and bi (1 ≤ ai ≤ n, 1 ≤ bi ≤ 109).

    Output

    For each of the Petya's assumptions output one integer, indicating the maximum length of a zip-line that can be built under this assumption.

    Sample Input

    4 4
    1 2 3 4
    1 1
    1 4
    4 3
    4 5

    Sample Output

    4
    3
    3
    4

    Hint

    题意

    给你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)这个很显然……

    然后就完了。

    细节部分,就是需要离散化一下,然后就没了,感觉还是很好写的。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e6+7;
    
    int n,m;
    int a[maxn],dp1[maxn],dp2[maxn];
    typedef int SgTreeDataType;
    struct treenode
    {
        int L , R  ;
        SgTreeDataType sum , lazy;
        void update(SgTreeDataType v)
        {
            sum = max(sum,v);
        }
    };
    struct Seg
    {
        treenode tree[maxn*4];
        inline void push_down(int o)
        {
    
        }
    
        inline void push_up(int o)
        {
            tree[o].sum = max(tree[2*o].sum , tree[2*o+1].sum);
        }
    
        inline void build_tree(int L , int R , int o)
        {
            tree[o].L = L , tree[o].R = R,tree[o].sum = 0;
            if (R > L)
            {
                int mid = (L+R) >> 1;
                build_tree(L,mid,o*2);
                build_tree(mid+1,R,o*2+1);
            }
        }
    
        inline void update(int QL,int QR,SgTreeDataType v,int o)
        {
            int L = tree[o].L , R = tree[o].R;
            if (QL <= L && R <= QR) tree[o].update(v);
            else
            {
                push_down(o);
                int mid = (L+R)>>1;
                if (QL <= mid) update(QL,QR,v,o*2);
                if (QR >  mid) update(QL,QR,v,o*2+1);
                push_up(o);
            }
        }
    
        inline SgTreeDataType query(int QL,int QR,int o)
        {
            int L = tree[o].L , R = tree[o].R;
            if (QL <= L && R <= QR) return tree[o].sum;
            else
            {
                push_down(o);
                int mid = (L+R)>>1;
                SgTreeDataType res = 0;
                if (QL <= mid) res = max(res, query(QL,QR,2*o));
                if (QR > mid) res = max(res, query(QL,QR,2*o+1));
                push_up(o);
                return res;
            }
        }
    }L,R;
    
    map<int,int> H;
    vector<int> P;
    struct node
    {
        int x,y;
    }Q[maxn];
    vector<pair<int,int> > Qx[maxn];
    int cnt[maxn];
    int dp3[maxn],dp4[maxn];
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]),P.push_back(a[i]);
        for(int i=1;i<=m;i++)
            scanf("%d%d",&Q[i].x,&Q[i].y),P.push_back(Q[i].y);
    
        sort(P.begin(),P.end());
        P.erase(unique(P.begin(),P.end()),P.end());
        for(int i=0;i<P.size();i++)
            H[P[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],Qx[Q[i].x].push_back(make_pair(i,Q[i].y));
        L.build_tree(1,P.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<Qx[i].size();j++)
            {
                int id = Qx[i][j].first;
                int x = Qx[i][j].second;
                dp3[id]=L.query(1,x-1,1)+1;
            }
            L.update(a[i],a[i],dp1[i],1);
        }
        reverse(a+1,a+1+n);
        R.build_tree(1,P.size()+5,1);
        for(int i=1;i<=n;i++)
        {
            dp2[i]=R.query(a[i]+1,P.size(),1)+1;
            for(int j=0;j<Qx[n-i+1].size();j++)
            {
                int id = Qx[n-i+1][j].first;
                int x = Qx[n-i+1][j].second;
                dp4[id]=R.query(x+1,P.size(),1)+1;
            }
            R.update(a[i],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
    ",ans);
        }
    }
  • 相关阅读:
    【sql:练习题3】查询在 SC 表存在成绩的学生信息
    【sql:练习题2】查询平均成绩大于等于 60 分的同学的学生编号和学生姓名和平均成绩
    学习设计模式之动态代理
    学习设计模式之静态代理
    学习设计模式之装饰器模式
    学习设计模式之策略模式
    学习设计模式之简单工厂
    Ehcache3.x学习(二)分层的选项
    Ehcache3.x学习(一)入门
    java进行微信h5支付开发
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5256432.html
Copyright © 2011-2022 走看看