zoukankan      html  css  js  c++  java
  • 【树状数组】【P3902】 递增

    传送门

    Description

    给你一个长度为(n)的整数数列,要求修改最少的数字使得数列单调递增

    Input

    第一行为(n)

    第二行(n)个数代表数列

    Output

    输出一行代表答案

    Hint

    (For~All:)

    (1~leq~n~leq~10^5)

    Solution

    看了下题目的意思貌似允许修改成实数,所以这里求一个LIS就完事了。但是发现(n^2)的LIS会爆炸,然而我又不会用单调性二分的(O(nlogn))的做法,于是自己口胡了一个树状数组的做法。

    在此声明一下这个做法有点水所以不能确定是不是有人提出过。但我确实口胡出来了

    显然读入可以离散化。离散化以后把DP的状态定义改变一下,设(f_i)为当前算到的以(i)为结尾的LIS的ans。

    考虑转移,显然正向DP时对于一个新位置(f_i=max{f_j}+1),其中(j~<~i)。发现(f_i)转移是由一个小于(i)的前缀(max)转移来的。

    于是可以树状数组维护这个前缀(max),更新(f_i)以后在树状数组上更新一下就好

    Code

    #include<cmath>
    #include<cstdio>
    #include<algorithm>
    #define rg register
    #define ci const int
    #define cl const long long int
    
    typedef long long int ll;
    
    namespace IO {
    	char buf[300];
    }
    
    template <typename T>
    inline void qr(T &x) {
    	rg char ch=getchar(),lst=' ';
    	while((ch > '9') || (ch < '0')) lst=ch,ch=getchar();
    	while((ch >= '0') && (ch <= '9')) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    	if(lst == '-') x=-x;
    }
    
    template <typename T>
    inline void qw(T x,const char aft,const bool pt) {
    	if(x < 0) {putchar('-');x=-x;}
    	rg int top=0;
    	do {
    		IO::buf[++top]=x%10+'0';
    	} while(x/=10);
    	while(top) putchar(IO::buf[top--]);
    	if(pt) putchar(aft);
    }
    
    template <typename T>
    inline T mmax(const T a,const T b) {return a > b ? a : b;}
    template <typename T>
    inline T mmin(const T a,const T b) {return a < b ? a : b;}
    template <typename T>
    inline T mabs(const T a) {return a < 0 ? -a : a;}
    
    template <typename T>
    inline void mswap(T &a,T &b) {
    	T _temp=a;a=b;b=_temp;
    }
    
    const int maxn = 100010;
    
    int n;
    int MU[maxn],tree[maxn],frog[maxn],temp[maxn];
    
    int ask(int);
    void init_hash();
    void change(int,ci);
    
    inline int lowbit(ci x) {return x&(-x);}
    
    int main() {
    	qr(n);
    	for(rg int i=1;i<=n;++i) {qr(MU[i]);temp[i]=MU[i];}
    	init_hash();
    	for(rg int i=1;i<=n;++i) {
    		frog[MU[i]]=ask(MU[i]-1)+1;
    		change(MU[i],frog[MU[i]]);
    	}
    	qw(n-ask(n),'
    ',true);
    	return 0;
    }
    
    void init_hash() {
    	std::sort(temp+1,temp+1+n);
    	int *ed=std::unique(temp+1,temp+1+n);
    	for(rg int i=1;i<=n;++i) MU[i]=std::lower_bound(temp+1,ed,MU[i])-temp;
    }
    
    int ask(int x) {
    	int _ans=0;
    	while(x) {
    		_ans=mmax(_ans,tree[x]);
    		x-=lowbit(x);
    	}
    	return _ans;
    }
    
    void change(int x,ci v) {
    	while(x <= n) {
    		tree[x]=mmax(tree[x],v);
    		x+=lowbit(x);
    	}
    }
    

    Summary

    以后麻麻再也不用担心我不会(O(nlogn))求LIS辣!

  • 相关阅读:
    AAPay v1.5使用介绍
    我的第一款实用工具眼保程序(EyesBaby)
    C/C++中const关键字详解
    go 中flag模块
    go语言的一些基础知识
    12.Redis6中的新的数据类型
    性能测试实战30讲笔记——2.性能分析思路
    11.redis6的发布与订阅(编号大小无关内容)
    k8s——1.k8s介绍
    Docker——容器数据卷
  • 原文地址:https://www.cnblogs.com/yifusuyi/p/9827802.html
Copyright © 2011-2022 走看看