http://acm.fzu.edu.cn/problem.php?pid=2320
显然是切得越多答案越小
那么就从左到右枚举切一刀的位置,维护两个树状数组,左边的数字情况和右边的数字情况。
那么向右挪动一位,就相当于把a[i]从右边换到左边,那么就减去a[i]与右边数字组成逆序对的数量,加上a[i]与左边组成逆序对的数量就行了。
#include<cstdio>
#include<algorithm>
#define pb push_back
using namespace std;
typedef long long ll;
const int maxl=3e5+10;
int n,m,cas,k,cnt,tot;ll ans;
int a[maxl],bl[maxl],br[maxl];
char s[maxl];
bool in[maxl];
inline void prework()
{
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),bl[i]=br[i]=0;
}
inline void add(int b[],int i,int x)
{
while(i<=n)
{
b[i]+=x;
i+=i&-i;
}
}
inline ll sum(int b[],int i)
{
ll ret=0;
while(i)
{
ret+=b[i];
i-=i&-i;
}
return ret;
}
inline void mainwork()
{
ll ansl=0,ansr=0;
for(int i=1;i<=n;i++)
{
ansr+=sum(br,n)-sum(br,a[i]);
add(br,a[i],1);
}
ans=0;
for(int i=1;i<=n-1;i++)
{
ansl+=sum(bl,n

本文介绍了一种在ACM竞赛中优化逆序对计算的策略,通过使用两个树状数组分别维护左右两边的数字情况,实现高效地计算随着切割位置变化的逆序对数量,从而找到最优解。
最低0.47元/天 解锁文章
535

被折叠的 条评论
为什么被折叠?



