hdu 2492(树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2492

Ping pong

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 4011    Accepted Submission(s): 1482

Problem Description

N(3<=N<=20000) ping pong players live along a west-east street(consider the street as a line segment).

Each player has a unique skill rank. To improve their skill rank, they often compete with each other. If two players want to compete, they must choose a referee among other ping pong players and hold the game in the referee‘s house. For some reason, the contestants
can’t choose a referee whose skill rank is higher or lower than both of theirs.

The contestants have to walk to the referee’s house, and because they are lazy, they want to make their total walking distance no more than the distance between their houses. Of course all players live in different houses and the position of their houses are
all different. If the referee or any of the two contestants is different, we call two games different. Now is the problem: how many different games can be held in this ping pong street?

Input

The first line of the input contains an integer T(1<=T<=20), indicating the number of test cases, followed by T lines each of which describes a test case.

Every test case consists of N + 1 integers. The first integer is N, the number of players. Then N distinct integers a1, a2 … aN follow, indicating the skill rank of each player, in the order of west to east. (1 <= ai <= 100000, i = 1 … N).

Output

For each test case, output a single line contains an integer, the total number of different games.

Sample Input

1
3 1 2 3

Sample Output

1

Source

2008 Asia Regional Beijing

Recommend

gaojie   |   We have carefully selected several similar problems for you:  2485 2491 2490 2489 2488

题意:有n个参赛选手位于一条直线上,每个选手有自己的一个技能值,每两个选手之间进行一场比赛需要到一个裁判家里去,并且裁判只能位于这两个选手的中间,问最后最多能有多少场比赛;

思路:再分析一下问题,相当于如果一个选手作为裁判,那么只要求出他左边有多少个比他技能值大的选手,求出右边有多少个比他技能值小的选手个数相乘,再加上,左边有多少个比他技能值小的选手,右边有多少个比他技能值大的选手相乘;

所以可以考虑用树状数组来求;

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
const int N=20000+1000;
using namespace std;

struct node
{
 int value,id;
}a[N];
bool cmp(node a,node b)
{
  return a.value<b.value;
}

int b[N],n,c[N];
int lmin[N],lmax[N],rmin[N],rmax[N];

int lowbit(int x)
{
 return x&(-x);
}

void updata(int x,int d)
{
 while(x<=n)
 {
  c[x]+=d;
  x+=lowbit(x);
 }
}

int getsum(int x)
{
 int ans=0;
 while(x>0)
 {
  ans+=c[x];
  x-=lowbit(x);
 }
 return ans;
}

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
     scanf("%d",&n);
     for(int i=1;i<=n;i++)
     {
       scanf("%d",&a[i].value);
       a[i].id=i;
     }
     sort(a+1,a+1+n,cmp);
     for(int i=1;i<=n;i++)b[a[i].id]=i;
     memset(c,0,sizeof(c));
     for(int i=1;i<=n;i++)
     {
       lmin[i]=getsum(b[i]);
       lmax[i]=i-1-lmin[i];
       updata(b[i],1);
     }
     memset(c,0,sizeof(c));
     for(int i=n,j=1;i>=1;i--,j++)
     {
       rmin[i]=getsum(b[i]);
       rmax[i]=j-1-rmin[i];
       updata(b[i],1);
     }
     long long cnt=0;
     for(int i=1;i<=n;i++)
     {
      long long temp=lmin[i]*rmax[i]+lmax[i]*rmin[i];
      cnt+=temp;
     }
     printf("%I64d\n",cnt);
    }
    return 0;
}
时间: 2024-07-28 12:57:05

hdu 2492(树状数组)的相关文章

Hdu 2492 树状数组 Ping pong

1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define MAXN 100005 5 #define M 20005 6 typedef __int64 LL ; 7 using namespace std; 8 LL n,max_num ; 9 LL s[M],a[M],b[M],c[MAXN]; 10 LL lowbit(LL x){ 11 return x&(-x); 12

hdu 3333 树状数组+离线处理

http://acm.hdu.edu.cn/showproblem.php?pid=3333 不错的题,想了很久不知道怎么处理,而且答案没看懂,然后找个例子模拟下别人的代码马上懂了---以后看不懂的话就拿个例子模拟下别人的代码 举个例子:1 3 3 5 3 5 查询 a, 2 4 b, 2 5 最初是这么想的:对于a查询,倘若把第二个数第三个数变成1个3,那么到b查询,又出现了两个3,再做处理似乎还是O(n),而且如果先出现2,5查询,后出现2,4查询,那么还需要把删除的数补回来.....o(╯

Hdu 3887树状数组+模拟栈

题目链接 Counting Offspring Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1757    Accepted Submission(s): 582 Problem Description You are given a tree, it’s root is p, and the node is numbered fr

Wikioi 2492 树状数组+并查集(单点更新区间查询)

刚开始做的时候用线段树做的,然后就跳进坑里了--因为要开方,所以区间的值都得全部变,然后想用lazy标记的,但是发现用不了,单点更新这个用不了,然后就不用了,就T了.然后实在不行了,看了别人的题解,原来是用树状数组+并查集的方法,唉--没想到啊! 因为开方之后多次那个数就会变成1了,所以是1的时候开方下去就没用了.树状数组更新的时候就把其更新的差更新即可,太机智了这题-- 昨天做了,然后出错找了好久都找不出来,原来是把s[i]写成c[i]了,然后答案一直错,晕-- #include <iostr

HDU 1754 树状数组 解法

mnesia在频繁操作数据的过程可能会报错:** WARNING ** Mnesia is overloaded: {dump_log, write_threshold},可以看出,mnesia应该是过载了.这个警告在mnesia dump操作会发生这个问题,表类型为disc_only_copies .disc_copies都可能会发生. 如何重现这个问题,例子的场景是多个进程同时在不断地mnesia:dirty_write/2 mnesia过载分析 1.抛出警告是在mnesia 增加dump

HDU 1166(树状数组)

用树状数组把HDU1166再写了一次  感觉树状数组简洁 1 #include <cstdio> 2 #include <iostream> 3 #include <string.h> 4 using namespace std; 5 int c[50002],lv[50002],n; 6 int lowbit(int x){return x&(-x);} 7 int sum(int b){ 8 int sum=0; 9 while(b>0){ 10 su

hdu 4368 树状数组 离线维护

http://acm.hdu.edu.cn/showproblem.php?pid=4638 Problem Description There are n men ,every man has an ID(1..n).their ID is unique. Whose ID is i and i-1 are friends, Whose ID is i and i+1 are friends. These n men stand in line. Now we select an interv

hdu 4630 树状数组+离线操作+GCD

http://acm.hdu.edu.cn/showproblem.php?pid=4630 重新认识了树状数组. 首先要记住那个树形的图,然后+或-lowbit(i)是自己根据具体问题设定的,不要死于+或者-, 树状数组的特点: 1.+lowbit(i)可以到达包含结点i的上一层父节点    所以用于值的更改 2.-lowbit(i)可以到达不包含i所代表区间的上一层父节点  所以用于值的求和---每个不相交的段加起来 3.C[i]的含义也是根据具体问题去做设定的,但是c[i]覆盖了a[i-2

HDU 1394 树状数组(逆序数)

Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 10100    Accepted Submission(s): 6192 Problem Description The inversion number of a given number sequence a1, a2, ..., an