蓝桥杯真题训练 五一 3/5

1215 小朋友排队

题目被喂了一下,知道是求逆序对的题目,一开始也想到了排序,看题解有人用归并排序做。树状数组以前学过,忘记了,看了一手代码,又会了。
二进制表示下最低位1及其后面的0构成的数值:lowbit(x) —> x & -x —> x & (~x+1) 取反加一。
有些地方都写在注释里了。那再说一下思路:
为什么做两遍树状数组,因为一个数的逆序对数,就是在它之前比它大的数,加上在它之后比它小的数。有了这个关系我们可以知道,一遍是为了求比在i之前,比当前(第i个)数大的数;一遍是为了求在i之后,比当前数小的数。所以才有了第一遍1~ n,第二遍n~ 1。
树状数组的概念就不赘述了,就是每隔2^i次计算一下前面数的和,比前缀和高级(快),跳着加,因为有lowbit这个特性。但是区间求和的时候如果左右边界不是2的倍数,还是要慢慢找一会儿,比遍历要快。(l,r)— l>=2 ^ i — r<=2 ^ i+j 就在这个(i~i+1)和(i+j-1,i+j)的区间里把累加和找出来就成,其它的区间和可以直接相减获得,和前缀和找区间和做法相同。(和这题没关系)
求出逆序对后,根据题意,每个小朋友有多少个逆序对,就交换了几次顺序,那不满意值根据逆序对个数n算一个等差数列的前n项和,再把每个小朋友的不满意值累加即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+100;
int n;
ll a[maxn];
ll tree[maxn];
ll b[maxn];//逆序对数
int lowbit(int x){
    return x&-x;
}
void add(int x,int y){
    for(int i=x;i<maxn;i+=lowbit(i)) tree[i]+=y;
}
int query(int x){
    int ans=0;
    for(int i=x;i;i-=lowbit(i)) ans+=tree[i];
    return ans;
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        a[i]++;
    }
    for(int i=1;i<=n;i++){
        //i 表示当前插入了几个数
        add(a[i],1);// 每个数插入的权值为1
        b[i]=i-query(a[i]);//在i之前 有多少个比i大的数被插入
    }
    memset(tree,0,sizeof(tree));//再做一遍 树状数组
    for(int i=n;i>=1;i--){
        add(a[i],1);
        b[i]+=query(a[i]-1);//在i i+1~n 有多少个数比i小 
    }
    ll res=0;
    for(int i=1;i<=n;i++){
        res+=(1+b[i])*b[i]/2;//等差数列求前n项和公式
    }
    cout<<res;
    //system("pause");
    return 0;
}

1219 移动距离

#include<bits/stdc++.h>
using namespace std;
int w,m,n;
int main(){
    cin>>w>>m>>n;
    int x,y,xx,yy;
    m--;
    n--;
    x=m/w;
    y=m%w;
    xx=n/w;
    yy=n%w;
    if(x%2==1) y=(w-y-1)%w;
    if(xx%2==1) yy=(w-yy-1)%w;
    cout<<abs(x-xx)+abs(y-yy);
    //system("pause");
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值