zoukankan      html  css  js  c++  java
  • BZOJ 4553: [Tjoi2016&Heoi2016]序列

    Description

     佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他。玩具上有一个数列,数列中某些项的值

    可能会变化,但同一个时刻最多只有一个值发生变化。现在佳媛姐姐已经研究出了所有变化的可能性,她想请教你
    ,能否选出一个子序列,使得在任意一种变化中,这个子序列都是不降的?请你告诉她这个子序列的最长长度即可
    。注意:每种变化最多只有一个值发生变化。在样例输入1中,所有的变化是:
    1 2 3
    2 2 3
    1 3 3
    1 1 31 2 4
    选择子序列为原序列,即在任意一种变化中均为不降子序列在样例输入2中,所有的变化是:3 3 33 2 3选择子序列
    为第一个元素和第三个元素,或者第二个元素和第三个元素,均可满足要求

    Input

     输入的第一行有两个正整数n, m,分别表示序列的长度和变化的个数。接下来一行有n个数,表示这个数列原始的

    状态。接下来m行,每行有2个数x, y,表示数列的第x项可以变化成y这个值。1 <= x <= n。所有数字均为正整数
    ,且小于等于100,000

    Output

     一个整数

    Sample Input

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

    Sample Output

    3
    对于这道题记录每个节点的最大值和最小值,然后就可以通过Dp来搞了,最开始我没看题,没有看到只有一个数值可以变化,然后就想了一个蠢蠢的dp : f[i]=max{f[j]}+1,max[j]<=min[i],i<j;然后树状数组求最大值就好了,后来感觉不太对(因为评论一片树套树),然后又看了一边题就发现了,dp应为f[i]=max{f[j]}+1,max[j]<=a[i],a[j]<=min[i],然后就有了两维的限制,开始蠢蠢的用二维树状数组发现开不下空间,然后只好去打树状数组套线段树,然后写个函数还忘记写返回值了。心累。。

    code:

    #define MAXN 100005
    #define inf 0x3f3f3f3f
    #define lowbit(x) ((x)&(-x))
    #include <bits/stdc++.h>
    using namespace std;
    int n,m,min_x[MAXN],max_x[MAXN],max_num;
    int f[MAXN],ans,a[MAXN];
     
     
    template<typename _t>
    inline _t read(){
        _t x=0;
        int f=1;
        char ch=getchar();
        for(;ch>'9'||ch<'0';ch=getchar())if(ch=='-')f=-f;
        for(;ch<='9'&&ch>='0';ch=getchar())x=x*10+(ch^48);
        return (_t)x*f;
    }
     
    struct node{
        node *ls,*rs;
        int max_x;
    	
    	node(){
            ls=rs=NULL;
            max_x=0;
        }
     
        inline int lm_(){return ls?ls->max_x:0;}
        inline int rm_(){return rs?rs->max_x:0;}
     
        void Maintain(){
    		max_x=max(lm_(),rm_());
        }
        
    }*root[MAXN];
     
    void insert(node *&o,int l,int r,int x,int w){
        if(!o)o=new node();
        if(l==r){
            o->max_x=w;
            return;
        }
        int m=l+r>>1;
        if(x<=m)insert(o->ls,l,m,x,w);
        else insert(o->rs,m+1,r,x,w);
        o->Maintain();
    }
     
    int query(node *o,int l,int r,int x,int y){
        if(!o)return 0;
        if(x<=l&&r<=y)return o->max_x;
        int m=l+r>>1,ans=0;
        if(x<=m)ans=max(ans,query(o->ls,l,m,x,y));
        if(m<y)ans=max(ans,query(o->rs,m+1,r,x,y));
        return ans;
    }
     
    void Updata(int x,int y,int w){
        for(;x<=max_num;x+=lowbit(x))
            insert(root[x],1,max_num,y,w);
    }
     
    inline int qmax(int x,int y){
        int ans = 0;
        for(;x;x-=lowbit(x))ans=max(ans,query(root[x],1,max_num,1,y));
        return ans;
    }
     
    int main(){
        n=read<int>();m=read<int>();
        for(int i=1;i<=n;i++){
            a[i]=read<int>(),min_x[i]=a[i],max_x[i]=min_x[i];
            max_num=max(max_num,a[i]);
        }
        for(int i=1,u,v;i<=m;i++){
            u=read<int>();
            v=read<int>();
            min_x[u]=min(v,min_x[u]);
            max_x[u]=max(v,max_x[u]);
            max_num=max(max_num,v);
        }
        for(int i=1;i<=n;i++)f[i]=1;
        for(int i=1;i<=n;i++){
            f[i]=max(f[i],qmax(a[i],min_x[i])+1);
            Updata(max_x[i],a[i],f[i]);
            ans = max(ans,f[i]);
        }
        cout << ans << endl;
    }





  • 相关阅读:
    SPOJ SAMER08A
    SPOJ TRAFFICN
    CS Academy Set Subtraction
    CS Academy Bad Triplet
    CF Round 432 C. Five Dimensional Points
    CF Round 432 B. Arpa and an exam about geometry
    SPOJ INVCNT
    CS Academy Palindromic Tree
    身体训练
    简单瞎搞题
  • 原文地址:https://www.cnblogs.com/Cooook/p/7738517.html
Copyright © 2011-2022 走看看