您的位置:首页 > 其它

HDU 1394 Minimum Inversion Number 线段树

2016-10-08 10:51 417 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394

代码:

#include <bits/stdc++.h>
#define sf scanf
#define pf printf
using namespace std;
/** 线段树模板 */
/** 以求区间和为例 */
#define lson rt << 1 , l ,mid
#define rson rt << 1 | 1,mid + 1,r
const int maxn = 50000 + 50;
int v[maxn << 2],laze[maxn << 2];
int A[maxn];

// 向下Push laze标记
void PushDown(int rt,int l,int r){
if(laze[rt]){
int mid = l + r >> 1,lcnt = mid - l + 1,rcnt = r - mid;
v[rt << 1] = v[rt << 1] + lcnt * laze[rt];
v[rt << 1 | 1] = v[rt << 1 | 1] + rcnt * laze[rt];
laze[rt << 1] += laze[rt];laze[rt << 1 | 1] += laze[rt];
laze[rt] = 0;
}
}
//向上更新sum值
void PushUp(int rt){
v[rt] = v[rt << 1] + v[rt << 1 | 1];
}
void Build(int rt,int l,int r){
if(l == r){
v[rt] = A[l];return;
}
int mid = l + r >> 1;
Build(lson),Build(rson);
laze[rt] = 0;
PushUp(rt);
}

//将区间L,R 增加X
void Update(int rt,int l,int r,int L,int R,int x){
if(L <= l && R >= r){
v[rt] += x * (r - l + 1);
laze[rt] += x;
return;
}
PushDown(rt,l,r);
int mid = l + r >> 1;
if(L <= mid) Update(lson,L,R,x);
if(R > mid) Update(rson,L,R,x);
PushUp(rt);
}

int Query(int rt,int l,int r,int L,int R){
if(L <= l && R >= r){
return v[rt];
}
PushDown(rt,l,r);
int mid = l + r >> 1;
int ret = 0;
if(L <= mid) ret += Query(lson,L,R);
if(R > mid) ret += Query(rson,L,R);
PushUp(rt);
return ret;
}

int num[maxn],tmp[maxn];
int main(){
int n;
while( ~sf("%d",&n) ){
int ret = 0,ans,x;
memset(A,0,sizeof A);
Build(1,1,n);
for(int i = 1;i <= n;++i){
sf("%d",&num[i]);num[i]++;
ret += (tmp[i] = Query(1,1,n,num[i],n));
Update(1,1,n,num[i],num[i],1);
}ans = ret;
for(int i = 1;i < n;++i){
ret -= num[i] - 1;
ret += n - num[i];
ans = min(ans,ret);
}
pf("%d\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: