HDU-5792

来源:互联网 发布:淘宝网pc客户端下载 编辑:程序博客网 时间:2024/06/06 02:50

点击打开题目链接

World is Exploding

Problem Description
Given a sequence A with length n,count how many quadruple (a,b,c,d) satisfies:abcd,1a<bn,1c<dn,Aa<Ab,Ac>Ad.
 

Input
The input consists of multiple test cases.
Each test case begin with an integer n in a single line.

The next line contains n integers A1,A2An.
1n50000
0Ai1e9
 

Output
For each test case,output a line contains an integer.
 

Sample Input
42 4 1 341 2 3 4
 

Sample Output
10

题意很明确,就是让我们求一个四元组,满足 a<b并且c<d.
解题思路:可以求出所有的四元组数目减去不符合条件四元组的数目,就可以得到我们需要的了。具体怎么实现呢,做这个题顺便学习了一下树状数组(百度百科有很详细的解释),真是很神奇的东西。但是这道题确实让我转了很大的圈子。具体解释详见代码。


#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cstring>using namespace std;long long a[50001],b[50001],c[50001],aa[50001];long long yx[50001],yd[50001],zx[50001],zd[50001];long long n;long long num; // 这里全部用 long long 是为了省事儿 long long get_k(long long k){return k&-k;}void add(long long pos,long long val){while(pos<=n){c[pos] += val; // 数组c是用来存储树状数组的值 pos += get_k(pos);}return ;}long long get_sum(long long pos){long long ans = 0;while(pos>0){      ans += c[pos];      pos -= get_k(pos);}   return ans;}   // 以上三个函数为对树状数组的操作 ,百度百科可以很详细的学习树状数组。 int main(){    while(scanf("%lld",&n)!=EOF)    {memset(c,0,sizeof(c));memset(a,0,sizeof(a));memset(b,0,sizeof(b));memset(yx,0,sizeof(yx));memset(yd,0,sizeof(yd));memset(zx,0,sizeof(zx));memset(zd,0,sizeof(zd)); for(int i=1;i<=n;i++){scanf("%lld", &a[i]);b[i] = a[i];}sort(b+1,b+1+n);    num = unique(b+1,b+1+n) - (b+1); //排序去重,方便离散化,其实这一步有没有都能AC。         long long sum1,sum2;    sum1 = sum2 = 0;    //两个for循环,正反各一次 for(int i=1;i<=n;i++)  {long long pos = lower_bound(b+1,b+1+num,a[i]) - b; // 每次找到a[i]的位置,如果没用unique,num就改为n add(pos,1);zx[i] =  get_sum(pos-1); //左边比a[i]小的数目 zd[i] =  i - get_sum(pos);//左边比a[i]大的数目 }   memset(c,0,sizeof(c)); // 反向循环的时候树状数组要清空重建    for(int i=n; i>=1; i--)   {       long long pos = lower_bound(b+1,b+1+n,a[i]) - b;       add(pos,1);       yx[i] = get_sum(pos-1);   //  右边比a[i]小的数目        yd[i] = n-i+1 - get_sum(pos); //右边比a[i]大的数目         sum1 += yx[i];sum2 += yd[i];}   long long pp = sum1 * sum2; // 所有的四元组       /*重复的情况有四种    即 ac重复,ad重复,bc重复,bd重复      */    for(int i=1;i<=n;i++)   { pp -= zx[i]*yx[i]; pp -= zd[i]*yd[i]; pp -= zx[i]*zd[i]; pp -= yx[i]*yd[i];   }   printf ("%lld\n",pp);  }return 0;}

水波








0 0