CF1637H

分析贡献,子序列内部贡献和对外面的贡献分开算。
取下标为 i1,i2,,ik 的子序列,设 di=j=1i1[pj>pi][pj<pi>]
则外部贡献为 di1
内部贡献为 (k2)2inv({pij})

上面都是我能做的

然后出现了性质:对于原序列中的逆序对 (i,j) ,只选 j 是比只选 i 不劣的。
证明见:https://www.cnblogs.com/PinkRabbit/p/CF1637.html
大概是反正,取距离最近一组不合法数对,分析贡献。

那么最终选得的每一个数,其后的所有逆序对都必选。
因此 inv({pij})=j=1kk=ij+1n[pk<pij]
因此一个数的贡献就是 ci=dik=i+1n[pk<pi]
排序后贪心取前 k 个。

结论的作用应该是把贡献具体到每个数上了。

#include<bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fd(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
typedef long long ll;
const int N=5e5+10;
int T,n,a[N],c[N],tr[N];
inline int query(int x){int ret=0; for(;x;x&=(x-1))ret+=tr[x]; return ret;}
inline void add(int x,int v){for(;x<=n;x+=(x&(-x)))tr[x]+=v;}
int main(){
	freopen("data.in","r",stdin);
	freopen("data.out","w",stdout);
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		fo(i,1,n)scanf("%d",&a[i]),tr[i]=c[i]=0;
		ll sum=0;
		fd(i,n,1){
			int v=query(a[i]);
			sum+=v;
			c[i]=(n-a[i])-(n-i-v);
			c[i]-=2*v+(a[i]-1-v);
			add(a[i],1);
		}
		sort(c+1,c+n+1,greater<int>());
		ll s=0;
		printf("%lld ",sum);
		fo(i,1,n){
			s+=c[i];
			printf("%lld ",sum-s-(ll)i*(i-1)/2);
		}
		printf("\n");
	}

	return 0;
}
posted @   Kelvin2005  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示