• 楼兰图腾(树状数组)


    题目:

    题目描述
    在完成了分配任务之后,西部314来到了楼兰古城的西部。

    相传很久以前这片土地上(比楼兰古城还早)生活着两个部落,一个部落崇拜尖刀(‘V’),一个部落崇拜铁锹(‘∧’),他们分别用V和∧的形状来代表各自部落的图腾。

    西部314在楼兰古城的下面发现了一幅巨大的壁画,壁画上被标记出了N个点,经测量发现这N个点的水平位置和竖直位置是两两不同的。

    西部314认为这幅壁画所包含的信息与这N个点的相对位置有关,因此不妨设坐标分别为(1,y1),(2,y2),…,(n,yn),其中y1~yn是1到n的一个排列。

    西部314打算研究这幅壁画中包含着多少个图腾。

    如果三个点(i,yi),(j,yj),(k,yk)满足1≤i[HTML_REMOVED]yj,yj<yk,则称这三个点构成V图腾;

    如果三个点(i,yi),(j,yj),(k,yk)满足1≤i[HTML_REMOVED]yk,则称这三个点构成∧图腾;

    西部314想知道,这n个点中两个部落图腾的数目。

    因此,你需要编写一个程序来求出V的个数和∧的个数。

    解题报告:

    咱们只需要求解的就是每个点左右两侧分别高于它和小于它的数目,就可以求出该点可以够成的V和A的数目,最后累加一下就可以,但是由于树状数组只可以求解该前边的的数目,所以转换了一下思想,就是使用getsum(n)-getsum(a[i]-1),就可以实现求解后边的数目。

    ac代码:

     1 //from:Onion
     2 //acwing 241  楼兰图腾  树状数组 
     3 
     4 #include<iostream>
     5 #include<algorithm>
     6 #include<cstring>
     7 #include<cstdio>
     8 #include<cmath> 
     9 using namespace std;
    10 typedef long long ll;
    11 
    12 int n;
    13 const int maxn =2e5+1000;
    14 ll a[maxn],t[maxn],left1[maxn],right1[maxn],left2[maxn],right2[maxn];
    15 
    16 ll lowbit(int x)
    17 {
    18     return x&-x;
    19 }
    20 void add(int x,int val)
    21 {
    22     while(x<=n)
    23     {
    24         t[x]+=val;
    25         x+=lowbit(x);
    26     }
    27 }
    28 ll getsum(int x)
    29 {
    30     ll ans=0;
    31     while(x>0)
    32     {
    33         ans+=t[x];
    34         x-=lowbit(x);
    35     }
    36     return ans;
    37 }
    38 
    39 int main()
    40 {
    41     scanf("%d",&n);
    42     ll mx=0;
    43     for(int i=1;i<=n;i++)    
    44     {
    45         scanf("%lld",&a[i]);
    46         mx=max(mx,a[i]); 
    47     }
    48     memset(t,0,sizeof(t));
    49     for(int i=n;i>0;i--)
    50     {
    51         right1[i]=getsum(n)-getsum(a[i]);
    52         right2[i]=getsum(a[i]-1);
    53         add(a[i],1);
    54     }
    55     memset(t,0,sizeof(t));
    56     ll ans1=0,ans2=0;
    57     for(int i=1;i<=n;i++)
    58     {
    59         left1[i]=getsum(n)-getsum(a[i]);
    60         left2[i]=getsum(a[i]-1);
    61         add(a[i],1);
    62         ans1+=left1[i]*right1[i];
    63         ans2+=left2[i]*right2[i];
    64     }
    65     printf("%lld %lld
    ",ans1,ans2);
    66 }
  • 相关阅读:
    Java Swing打猎射击游戏源码
    php实现在线下载程序安装包功能
    WP
    双人对战的球类游戏IOS源码
    非常不错的新闻客户端应用安卓源码
    创业建议:如何写挖人邮件
    wp8路线跟踪应用源码详细说明
    wp版笔记本应用源码
    旅游风景展示应用源码iPad版
    bitset优化背包
  • 原文地址:https://www.cnblogs.com/Spring-Onion/p/11335410.html
Copyright © 2020-2023  润新知