P1428 小鱼比可爱

时间:2023-03-08 15:40:07

P1428

题目描述

  人比人,气死人;鱼比鱼,难死鱼。小鱼最近参加了一个“比可爱”比赛,比的是每只鱼的可爱程度。参赛的鱼被从左到右排成一排,头都朝向左边,然后每只鱼会得到一个整数数值,表示这只鱼的可爱程度,很显然整数越大,表示这只鱼越可爱,而且任意两只鱼的可爱程度可能一样。由于所有的鱼头都朝向左边,所以每只鱼只能看见在它左边的鱼的可爱程度,它们心里都在计算,在自己的眼力范围内有多少只鱼不如自己可爱呢。请你帮这些可爱但是鱼脑不够用的小鱼们计算一下。

输入输出格式

输入格式:

  第一行输入一个整数n,表示鱼的数目。

  第二行内输入n个整数,用空格间隔,依次表示从左到右每只小鱼的可爱程度。

输出格式:

  行内输出n个整数,用空格间隔,依次表示每只小鱼眼中有多少只鱼不如自己可爱。

输入样例

6
4 3 0 5 1 2

输出样例

0 0 0 3 1 2

一般解法:

#include <bits/stdc++.h>
using namespace std;
int a[],b[],n;
int main(){
cin>>n;
for (int i=;i<=n;i++)//读入每条鱼的可爱值
cin>>a[i];
for (int i=;i<=n;i++)//枚举N条鱼
for (int j=i;j>=;j--){//从第I个位置倒着往前找
if (a[j]<a[i])
b[i]++;//如果找到比第I条鱼丑的,统计数组b对应的b[i]+1
}
for (int i=;i<=n;i++)
cout<<b[i]<<" ";//输出
return ;
}

树状数组逆序对

  1、构造结构体,然后根据可爱值的大小来排序,其实也是离散化,但是这里不需要专门用数组记录。

  2、因为已经根据可爱值的大小进行排序,所以就按值的大小进行标记,即将树状数组c加1。

  3、那么求逆序对就是求index-1前已经标记过的c的个数。

  4、对于这道题,将第i条鱼前面鱼的个数减去他前面逆序对的个数就是没有他可爱的鱼的个数。

代码如下:

#include <bits/stdc++.h>
using namespace std;
int n;
struct node{
int val,index;
}a[];
bool cmp(node a,node b){
return a.val>b.val;
}
bool cmp1(node a,node b){
return a.index<b.index;
}
int c[],ans[];
int lowbit(int x){
return x&(-x);
}
void update(int x,int val){
for(int i=x;i<=n;i+=lowbit(i))
c[i]+=;
}
int getsum(int x){
int tp=;
for(int i=x;i>;i-=lowbit(i))
tp+=c[i];
return tp;
}
int main(){
scanf("%d",&n);
for(int i=;i<=n;++i)
scanf("%d",&a[i].val),a[i].index=i;
sort(a+,a++n,cmp);
for(int i=;i<=n;++i){
update(a[i].index,);
ans[a[i].index]=getsum(a[i].index-);
}
sort(a+,a++n,cmp1);
for(int i=;i<=n;++i)
printf("%d ",i-ans[i]-);
return ;
}

动态开点的权值线段树:

代码如下:

#include<bits/stdc++.h>
#define maxn 107
#define maxnode 5007
#define maxval 2147483646
using namespace std; int n,a[maxn];
int tree[maxnode][],rt=,nodenum=; void PushUp(int rt){
tree[rt][]=tree[ tree[rt][] ][]+tree[ tree[rt][] ][];
} int query(int L,int R,int l,int r,int &rt){
if (rt==) return ; //[1] 若该点不存在,返回0(说明该点没有值)
if (L<=l && r<=R) return tree[rt][];
int m=(l+r)>>; int ANS=;
if (L<=m) ANS+=query(L,R,l,m,tree[rt][]);
if (R>m) ANS+=query(L,R,m+,r,tree[rt][]);
return ANS;
} void update(int L,int C,int l,int r,int &rt){
if (rt==){ //[2] 若该点不存在,新建改点
nodenum++;
rt=nodenum;
tree[nodenum][]=tree[nodenum][]=tree[nodenum][]=;
}
if (l==r){
tree[rt][]+=C;
return;
}
int m=(l+r)>>;
if (L<=m) update(L,C,l,m,tree[rt][]);
else update(L,C,m+,r,tree[rt][]);
PushUp(rt);
} int main(){
int n;
scanf("%d", &n);
for (int i=; i<=n; i++){
int val;
scanf("%d", &val);
printf("%d ",query(,val-,,maxval,rt));
update(val,+,,maxval,rt);
}
}