萌新求证时间复杂度
查看原帖
萌新求证时间复杂度
119261
7KByte楼主2020/8/10 18:24

这个类似莫队的神仙操作时间复杂度怎么证明啊

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define pre(i,a,b) for(int i=a;i>=b;i--)
#define N 25005
#define M 27
using namespace std;
int n,k,f[N][M],a[N],c[N];
inline void add(int x,int val){
	if(!x)return;
	for(;x<=n;x+=x&-x)c[x]+=val;
}
inline int ask(int x){
	int sum=0;
	for(;x;x-=x&-x)sum+=c[x];
	return sum;
}
int L,R,sum;
void change(int l,int r){
	while(L>l){
		add(a[--L],1);
		sum+=ask(n)-ask(a[L]);
	}
	while(R<r){
		add(a[++R],1);
		sum+=ask(a[R]-1);
	}
	while(R>r){
		sum-=ask(a[R]-1);
		add(a[R--],-1);
	}
	while(L<l){
		sum-=ask(n)-ask(a[L]);
		add(a[L++],-1);
	}
}
void solve(int l,int r,int ll,int rr,int op){
	if(l>r)return;
	int mid=(l+r)>>1;
	int mn=ll,val=0x3f3f3f3f;
	pre(i,min(rr,mid-1),ll){
		change(i+1,mid);
		if(sum+f[i][op-1]<=val)val=sum+f[i][op-1],mn=i;
	}	
	f[mid][op]=val;
	solve(l,mid-1,ll,mn,op);solve(mid+1,r,mn,rr,op);
}
int main(){
	scanf("%d%d",&n,&k);
	rep(i,1,n)scanf("%d",&a[i]);
	L=R=1;add(a[1],1);
	memset(f,0x3f,sizeof(f));
	f[0][0]=0;
	rep(j,1,k)
		solve(j,n,j-1,n-1,j);
	printf("%d\n",f[n][k]);
	return 0;
}
2020/8/10 18:24
加载中...