HDU_1394_线段数

http://acm.hdu.edu.cn/showproblem.php?pid=1394

线段数入门题,每次读入一个数,就寻找在树中比它大的值的个数,然后跟新数,把个数相加就是逆序数,每移动一个数,相当于当前逆序数加上比首元素大的数的数量,减去比首元素小的数的数量。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

struct segtree
{
    int left,right,sum;
}tree[10050];
int n,a[5050];

void build(int pos,int l,int r)
{
    tree[pos].left = l;
    tree[pos].right = r;
    tree[pos].sum = 0;
    if(l < r)
    {
        int mid = (l+r)/2;
        build(pos*2,l,mid);
        build(pos*2+1,mid+1,r);
    }
}

int getsum(int pos,int l,int r)
{
    if(tree[pos].left == l && tree[pos].right == r)   return tree[pos].sum;
    int mid = (tree[pos].left+tree[pos].right)/2;
    if(r <= mid)    return getsum(pos*2,l,r);
    if(l > mid)     return getsum(pos*2+1,l,r);
    return getsum(pos*2,l,mid)+getsum(pos*2+1,mid+1,r);
}

void update(int pos,int num)
{
    tree[pos].sum++;
    if(tree[pos].left == tree[pos].right)   return;
    int mid = (tree[pos].left+tree[pos].right)/2;
    if(num <= mid)  update(pos*2,num);
    else    update(pos*2+1,num);
}

int main()
{
    while(~scanf("%d",&n))
    {
        int ans = 0;
        build(1,0,n-1);
        for(int i = 0;i < n;i++)
        {
            scanf("%d",&a[i]);
            ans += getsum(1,a[i],n-1);
            update(1,a[i]);
        }
        int temp = ans;
        for(int i = 0;i < n-1;i++)
        {
            temp += n-1-a[i]-a[i];
            ans = min(temp,ans);
        }
        printf("%d\n",ans);
    }
    return 0;
}
时间: 2024-10-14 06:04:58

HDU_1394_线段数的相关文章

hdu1754(线段数维护区间最大值)

题意:给定1-n(n<=200000)个数,然后动态改变一些值,并动态询问区间最大值. 解法:裸的线段树,赛前默写模版回忆下线段树代码.仍然要注意:线段树节点数组一定要开到节点数的三倍长度. 代码: /****************************************************** * author:xiefubao *******************************************************/ #pragma comment(lin

poj 3264 Balanced Lineup(线段数求区间最大最小值)

链接:http://poj.org/problem?id=3264 Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 32772   Accepted: 15421 Case Time Limit: 2000MS Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order.

线段数 --- (单点更新、求逆序对)

Minimum Inversion Number Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that satisfy i < j and ai > aj. For

hdu 4719 Oh My Holy FFF(线段数+dp)

题目链接:hdu 4719 Oh My Holy FFF 题目大意:队伍里有n个人,给出每个人的身高,他们按照顺序排列,现在要将这n个人分成若干组,每一组的人数不得大于l,并且第i组的最后一个人的身高一定要大于第i?1组的最后一个人的身高.要求最后的权值最大,权值计算方法在题目中,k为组号. 解题思路:dp[i]表示以第i个人作为结尾的最大权值,那么dp[i]肯定是从前面的l-1个中转移过来的,即dp[i]=dp[j]+h[i]2?h[j] 要求h[i]>h[j]. 但是这样的复杂度为o(n2)

codeforces332B - Maximum Absurdity 线段数 or dp

题意:给你一个序列,找两个长度为 k 且没有重合区间的数使得其和最大 解题思路: 1)线段树 想了半天想不出只能先用线段树撸了一发,这题dp 第一名只要了 9分钟. 就是把起点为 i  长度为 k 的和预处理出来,再用线段树枚举去找. 解题代码: 1 // File Name: 332b.cpp 2 // Author: darkdream 3 // Created Time: 2014年07月30日 星期三 08时10分45秒 4 5 #include<vector> 6 #include&

线段数模板

单点更新(HDU1166) #include <cstdio> #include <iostream> using namespace std; const int MAXN=2e5+10; const int MAXNODE=MAXN<<2;//一般开到4倍 int sum; struct node { int l; int r; int value; }tree[MAXNODE]; int father[MAXN];//用来储存第x个元素在线段数的结点位置 void

(hdu step 1.3.2)今年暑假不AC(求在线段不重合的情况下同时共存的最大线段数)

题目: 今年暑假不AC Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 2608 Accepted Submission(s): 1407   Problem Description "今年暑假不AC?""是的.""那你干什么呢?""看世界杯呀,笨蛋!""@#$%

hdoj 1394 Minimum Inversion Number 【线段数】

题目大意:求移动数列中的第一个元素到最后一位时的最少逆序数.(进行n次移动,求移动过程中最少的逆序数) 难点: 一:什么是逆序数? 定义: 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数.逆序数为偶数的排列称为偶排列:逆序数为奇数的排列称为奇排列.如2431中,21,43,41,31是逆序,逆序数是4,为偶排列. 二:怎么求? 此题分析一下有个技巧:对于这道题因为是0~n-1所以我们可以通过下标就可以判

Minimum Inversion Number 【线段数】

Problem DescriptionThe inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that satisfy i < j and ai > aj. For a given sequence of numbers a1, a2, ..., an, if we move the first m >= 0 numbers to the end of