樹狀陣列upc1976

u010660276發表於2013-12-03

1976: problem F

Time Limit: 3 Sec  Memory Limit: 64 MB
Submit: 69  Solved: 10
[Submit][Status][Web Board]

Description

在一個小鎮上住著n位武林高手,他們互相之間經常PK,不過PK的時候必須要有一位裁判在場。這個小鎮上的房子從1—n依次排列(一條直線上),兩個人要單挑時必須到另一個人的家裡,讓這個人作為裁判,裁判的武功不能同時比兩個人低也不能同時比兩個人高。由於每個高手都很懶,所以他們走的路程不能比他倆之間的距離遠(即只能在他們序號之間高手中選擇裁判)。求小鎮上最多能進行幾場PK。

Input

先輸入一個整數T(T<=100),包含T組測試資料,每組資料先輸入n(n<=100000),然後後面是n個數,表示n個武林高手的功夫ai,(ai<=100000)。

Output

能夠進行的最大場數,每組資料佔一行。

Sample Input

231 2 352 2 2 2 2

Sample Output

110

思路:跟poj1990有些相似。
下面是程式碼:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAX=500010;
struct node
{
    long long x,value;
}a[MAX];
long long n;
long long num[MAX];
bool cmp(node a,node b)
{
    return a.value<b.value;
}
long long sum(long long x)
{
    long long sum=0;
    while(x>0)
    {
        sum+=num[x];
        x-=(x&(-x));
    }
    return sum;
}
void update(long long x,int cnt)
{
    while(x<=n)
    {
        num[x]+=cnt;
        x+=(x&(-x));
    }
}
int main()
{
    //freopen("test2.in","r",stdin);
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(long long i=1;i<=n;i++)
        {
            scanf("%lld",&a[i].value);
            a[i].x=i;
        }
        memset(num,0,sizeof(num));
        stable_sort(a+1,a+n+1,cmp);
        long long ans=0;
        for(long long  i=1;i<=n;i++)
        {
            long long x=sum(a[i].x);
            ans+=x*((n-a[i].x)-(i-x-1))+(a[i].x-x-1)*(i-x-1);
            update(a[i].x,1);
        }
        cout<<ans<<endl;
    }
    return 0;
}



相關文章