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

    BZOJ4553: [Tjoi2016&Heoi2016]序列

    Description

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

    玩具上有一个数列,数列中某些项的值可能会变化,但同一个时刻最多只有一个值发生变化。

    现在佳媛姐姐已经研究出了所有变化的可能性,她想请教你,能否选出一个子序列,使得在任意一种变化中,这个子序列都是不降的?

    请你告诉她这个子序列的最长长度即可。

    注意:每种变化最多只有一个值发生变化。

    在样例输入中,所有的变化是:

    1 2 3
    2 2 3
    1 3 3
    1 1 3
    1 2 4
    选择子序列为原序列,即在任意一种变化中均为不降子序列。

    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
    题解Here!

    很烦人的一题。。。

    蒟蒻表示并不会整体二分/cdq分治,只能弱弱地打出树状数组套平衡树。。。

    关键是我的 Splay 还写挂了,药丸。。。

    我们设:

    maxvi 为第 i 个数变化的最大值;

    minvi 为第 i 个数变化的最小值;

    ai 为原来的数值。

    则题目要求转化为:

    求一个最长的序列,使一下条件满足 i,maxaj​ maxvj​ ≤ ai .

    那这种不等式问题就能转化为二维数点问题。

    对于每一个 j ,我们每一次就可以在平面内加一个坐标为 maxvj​ aj​ ) 的权值为 dp[ j ] 的点;

    对于每一次转移,可以从 (0,0) 到 ai​ minvi​ ) 中找到一个点权最大的点,当前点答案就是找到点的权值+1。

    附代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define MAXN 200010
    using namespace std;
    int n,m,maxn=0;
    int num[MAXN],b[MAXN],c[MAXN],dp[MAXN];
    int size=1;
    struct node{
        node* son[2];
        int w,v,x,maxn;
        node(){
            son[0]=son[1]=NULL;
            w=rand();
        }
    };
    node* root[MAXN];
    inline int read(){
        int date=0,w=1;char c=0;
        while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
        while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
        return date*w;
    }
    inline int max(const int x,const int y){return x>y?x:y;}
    inline void maintain(node* &u){
        if(u==NULL)return;
        u->maxn=u->v;
        if(u->son[0]!=NULL)u->maxn=max(u->maxn,u->son[0]->maxn);
        if(u->son[1]!=NULL)u->maxn=max(u->maxn,u->son[1]->maxn);
    }
    inline void turn(node* &u,int f){
        node* t=u->son[f^1];
        u->son[f^1]=t->son[f];
        t->son[f]=u;
        maintain(u);
        maintain(t);
        u=t;
    }
    void insert(node* &u,int x,int v){
        if(u==NULL){
            u=new node;
            u->x=x;u->v=u->maxn=v;
            maintain(u);
            return;
        }
        else if(u->x==x){
            u->v=max(u->v,v);
            maintain(u);
            return;
        }
        int y=u->x<x?1:0;
        insert(u->son[y],x,v);
        if(u->son[y]->w>u->w)turn(u,y^1);
        maintain(u);
    }
    int query(node* u,int x){
        int s=0;
        while(u!=NULL){
            if(u->x>x)u=u->son[0];
            else{
                if(u->son[0]!=NULL)s=max(s,max(u->son[0]->maxn,u->v));
                else s=max(s,u->v);
                u=u->son[1];
            }
        }
        return s;
    }
    inline int lowbit(int x){return x&(-x);}
    void update(int x,int y,int v){
        for(int i=x;i<=maxn;i+=lowbit(i))insert(root[i],y,v);
    }
    int get_max(int x,int y){
        int s=0;
        for(int i=x;i;i-=lowbit(i))s=max(s,query(root[i],y));
        return s;
    }
    void work(){
        int ans=0;
        for(int i=1;i<=n;i++){
            dp[i]=get_max(b[i],num[i])+1;
            ans=max(ans,dp[i]);
            update(num[i],c[i],dp[i]);
        }
        printf("%d
    ",ans);
    }
    void init(){
        int x,y;
        n=read();m=read();
        for(int i=1;i<=n;i++)b[i]=c[i]=num[i]=read();
        for(int i=1;i<=m;i++){
            x=read();y=read();
            b[x]=min(b[x],y);
            c[x]=max(c[x],y);
        }
        for(int i=1;i<=n;i++)maxn=max(maxn,c[i]);
    }
    int main(){
        srand(798);
        init();
        work();
        return 0;
    }
    
  • 相关阅读:
    SQL server 事务介绍,创建与使用
    DOM操作系列-01
    JS键盘事件
    Js获取当前日期时间及其它操作
    js中!!的作用
    js == 与 === 的区别[转]
    学习总结--Dom
    css历史
    javascript中 visibility和display的区别
    “==”和Equals区别
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9315732.html
Copyright © 2011-2022 走看看