(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦
hdu1394求逆序对
传送门
读入一个数字,线段树求比他大的数的个数,累加,更新。
AC代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define mm0(a) memset((a),0,sizeof((a)))
#define lson rt<<1
#define rson rt<<1|1
#define lsonl rt<<1,l,m
#define rsonr rt<<1|1,m+1,r
using namespace std;
typedef long long LL;
const int N = 1e6+5;
int n,m;
struct lp{
int l,r;
int sum;
}cw[N<<2];
int ar[N],br[N];
void build(int rt,int l,int r){
cw[rt].l=l;cw[rt].r=r;
cw[rt].sum=0;
if(l==r){
return;
}
int m=(l+r)>>1;
build(lsonl);
build(rsonr);
}
void update(int rt,int p){
cw[rt].sum++;
if(cw[rt].l==cw[rt].r){
return;
}
int m=(cw[rt].l+cw[rt].r)>>1;
if(p<=m){
update(lson,p);
}else{
update(rson,p);
}
}
int query(int rt,int L,int R){
if(L>R)return 0;
if(L<=cw[rt].l&&cw[rt].r<=R){
return cw[rt].sum;
}
int m=(cw[rt].l+cw[rt].r)>>1;
if(L>m){
return query(rson,L,R);
}else if(R<=m){
return query(lson,L,R);
}else{
return query(lson,L,m)+query(rson,m+1,R);
}
}
int main(){
while(~scanf("%d",&n)){
for(int i=0;i<n;++i){
scanf("%d",&ar[i]);
ar[i]++;
}
build(1,1,n);
int ans=0;
for(int i=0;i<n;++i){
br[i]=query(1,ar[i]+1,n);
ans+=br[i];
update(1,ar[i]);
}
int ret=ans;
for(int i=0;i<n;++i){
ar[i]--;
ans=min(ans,ret-(ar[i])+(n-ar[i]-1));
ret=ret-(ar[i])+(n-ar[i]-1);
}
printf("%d\n",ans );
}
return 0;
}
//提一下树状数组求逆序对写法:
//不针对本题
#include<bits/stdc++.h>
#define lowbit(x) (x&(-x))
using namespace std;
typedef long long LL;
const int N = 1e5+7;
int n,q,tot;
int ar[N],bit[N];
void add(int x){
while(x<=n){
bit[x]++;
x += lowbit(x);
}
}
int query(int x){
int sum=0;
while(x){
sum+=bit[x];
x-=lowbit(x);
}
return sum;
}
int main(){
int tim;
scanf("%d", &tim);
while(tim--){
scanf("%d", &n);
for(int i=1;i<=n;++i){
scanf("%d", &ar[i]);
}
LL all=0;
memset(bit,0,sizeof(bit));
for(int i=1;i<=n;++i){
int p = ar[i];
int tmp = query(p);
all+=tmp;
add(p);
}
all=n*1LL*(n-1)/2-all;
printf("%lld\n", all);
}
return 0;
}
hdu5592还原逆序对
传送门
已知有前缀和逆序数个数数组p。
建权值线段树,记录区间内权值的个数。
p[i]-p[i-1]表示前i个数中有多少个数比它大。那么它就是第(i-(p[i]-p[i-1]))个数。
每确定一个数,减去该权值。
AC代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define lson rt<<1
#define rson rt<<1|1
#define lsonl rt<<1,l,m
#define rsonr rt<<1|1,m+1,r
using namespace std;
typedef long long LL;
const int N = 1e6+5;
int n,m;
struct lp{
int l,r;
int sum,val;
}cw[N<<2];
int ar[N],ans[N];
void build(int rt,int l,int r){
cw[rt].l=l;cw[rt].r=r;
cw[rt].sum=r-l+1;
if(l==r){
cw[rt].val=l;
return;
}
int m=(l+r)>>1;
build(lsonl);
build(rsonr);
}
void update(int rt,int p){
cw[rt].sum--;
if(cw[rt].l==cw[rt].r){
return;
}
int m=(cw[rt].l+cw[rt].r)>>1;
if(p<=m){
update(lson,p);
}else{
update(rson,p);
}
}
int query(int rt,int p){
if(cw[rt].l==cw[rt].r){
return cw[rt].val;
}
int m=(cw[rt].l+cw[rt].r)>>1;
if(p<=cw[lson].sum){
return query(lson,p);
}else{
return query(rson,p-cw[lson].sum);
}
}
int main(){
int tim;
scanf("%d",&tim);
while(tim--){
scanf("%d",&n);
ar[0]=0;
build(1,1,n);
for(int i=1;i<=n;++i){
scanf("%d",&ar[i]);
}
for(int i=n;i>=1;--i){
ans[i]=query(1,i-(ar[i]-ar[i-1]));
update(1,ans[i]);
}
for(int i=1;i<n;++i){
printf("%d ",ans[i] );
}
printf("%d\n",ans[n] );
}
return 0;
}