JZOJ6547 USACO USOpen 2020 Haircut 题解

口胡一下各种时间复杂度(也许吧)的方法

S o 1 u t i o n 1 So1ution1 So1ution1:直接上暴力

时间复杂度 O ( n 2 l o g n ) \text{时间复杂度}O(n^{2}logn) 时间复杂度O(n2logn)

S o l u t i o n 2 Solution2 Solution2: 考虑到相邻 k k k 之间变化量等于所有 k + 1 k+1 k+1 变到 k k k 导致逆序对的减量之和,因此算这个然后逆着推。

S o l u t i o n 3 Solution3 Solution3(正解):优化一下的方法应该很容易想到吧,可以转化为一个类似求逆序对的一个东东,然后就显然了。

注意开long long

C o d e Code Code

#include<cstdio>
#define ll long long

const int N = 1e5 + 5;
ll n, a[N], s[N], ans, t[N];

ll lowbit(ll x){return x & (-x);}
void update(ll x){while(x <= n) t[x]++, x += lowbit(x);}
ll query(ll x){ll ret = 0; while(x) ret += t[x], x -= lowbit(x); return ret;}

int main()
{
    freopen("haircut.in","r",stdin);
    freopen("haircut.out","w",stdout);
    scanf("%lld", &n);
    for(int i = 1; i <= n; i++) scanf("%lld", &a[i]), a[i]++;
    for(int i = 1; i <= n; i++)
        s[a[i]] += query(n - a[i] + 1), update(n - a[i] + 2);
    for(int i = 0; i < n; i++) ans += s[i], printf("%lld\n", ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值