【树状数组】【P3902】 递增

传送门

Description

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

Input

第一行为n

第二行n个数代表数列

Output

输出一行代表答案

Hint

For All:

1  n  105

Solution

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

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

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

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

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

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),'\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辣!

posted @   一扶苏一  阅读(673)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示