• 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 }
  • 相关阅读:
    UEditor 编辑模板
    Task ProgressBar模拟现实完成后显示TextBox
    Java Lambda map返回部分属性
    Socket编程
    字节流和字符流
    File类
    volatile的作用和原理
    Java四种引用类型
    ThreadLocal
    孤儿进程和僵尸进程
  • 原文地址:https://www.cnblogs.com/ITUPC/p/5730118.html
Copyright © 2020-2023  润新知