2016 Multi-University Training Contest 5 1012 World is Exploding 树状数组+离线化

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

1012 World is Exploding

题意:选四个数,满足a<b and A[a]<A[b]   c<d and A[c]>A[d] 问有几个这样的集合

思路:

树状数组+离线化

先处理出每个数左边比它小 大,右边比它大 小的数目,用cnt[][i]表示。最后统计一下减去重复的就可以

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <sstream>
  5 #include <string>
  6 #include <algorithm>
  7 #include <list>
  8 #include <map>
  9 #include <vector>
 10 #include <queue>
 11 #include <stack>
 12 #include <cmath>
 13 #include <cstdlib>
 14 using namespace std;
 15 typedef long long ll;
 16 ll cnt[4][50005];
 17 ll cnt1[50005],cnt2[50005];
 18 ll a[50005];
 19 
 20 struct Node{
 21     ll num,id;
 22 }sub_a[50005];
 23 
 24 
 25 ll maxn = 0;
 26 ll n;
 27 ll tree[100005];
 28 bool cmp(Node a, Node b) { //按照数字排序
 29     return a.num < b.num;
 30 }
 31 void discrete() { //离散化
 32     sort(sub_a+1, sub_a+1+n, cmp);
 33     a[sub_a[1].id] = 1;
 34     maxn = 1;
 35     for(ll i = 2; i <= n; i++) {
 36         if(sub_a[i].num != sub_a[i-1].num)
 37             a[sub_a[i].id] = i;
 38         else
 39             a[sub_a[i].id] = a[sub_a[i-1].id];
 40         maxn = max(maxn,a[sub_a[i].id]);
 41     }
 42 }
 43 void add(ll k){
 44     while(k <= n){
 45         tree[k] ++;
 46         k += k & (- k);
 47     }
 48 }
 49 ll read(ll k){
 50     ll ans = 0;
 51     while(k){
 52         ans += tree[k];
 53         k -= k &(-k);
 54     }
 55     return ans;
 56 }
 57 
 58 int main(){
 59     while(scanf("%I64d",&n) != EOF)
 60     {
 61         memset(cnt1,0,sizeof(cnt1));
 62         memset(cnt2,0,sizeof(cnt2));
 63         for(ll i = 1; i <= n; i ++){
 64             scanf("%I64d",&sub_a[i].num);
 65             sub_a[i].id = i;
 66         }
 67         discrete();
 68         memset(tree,0,sizeof(tree));
 69         //在它右侧比它小的
 70         for(ll i = n; i >= 1; i--){
 71 
 72             add(a[i]);
 73            cnt[0][i] = read(a[i] - 1);
 74         }
 75         //在它左侧比它小的
 76          memset(tree,0,sizeof(tree));
 77         for(ll i = 1; i <= n; i ++){
 78             add(a[i]);
 79             cnt[1][i] = read(a[i] - 1);
 80             a[i] = maxn + 1 - a[i];
 81         }
 82          //在它右侧比它大的
 83           memset(tree,0,sizeof(tree));
 84         for(ll i = n; i >= 1; i --){
 85 
 86             add(a[i]);
 87            cnt[2][i] = read(a[i] - 1);
 88         }
 89         //在它左侧比它大的
 90          memset(tree,0,sizeof(tree));
 91         for(ll i = 1; i <= n; i ++){
 92             add(a[i]);
 93             cnt[3][i] = read(a[i] - 1);
 94             a[i] = maxn + 1 - a[i];
 95         }
 96         ll cnta = 0,cntb = 0;
 97         for(ll i = 1; i <= n; i ++){
 98             cnt1[i] = cnt[0][i] + cnt[3][i];
 99             cnta += cnt1[i];
100             cnt2[i] = cnt[1][i] + cnt[2][i];
101              cntb += cnt2[i];
102         }
103         cnta = cnta / 2;
104         cntb = cntb / 2;
105         long long  ans = cnta * cntb;
106         for(ll i = 1; i <= n; i ++){
107             ans -= cnt1[i] * cnt2[i];
108         }
109         printf("%I64d
",ans);
110     }
111     return 0;
112 }
原文地址:https://www.cnblogs.com/ITUPC/p/5730118.html