• 【CH4201】楼兰图腾


    这道题我采用树状数组求解逆序对一类的思想解决

    我们读入数据之后,分析问题,本题求解两个问题:‘^’的数量和‘v’的数量,我们先考虑^

    假设我们令i为^的那个顶点,那么以i为顶点的^的个数就是i左侧高度小于i的高度的个数与右侧高度小于i的数量的乘积,我们只需要枚举i的位置,累加答案即可。

    我们如何高效的维护i两侧小于i高度的数量?我们建立一个树状数组(当然线段树也可以)存储每一个高度出现的次数。

    我们正序枚举i,对于每一个i,我们在树状数组中查找0~a[i]-1的数量,这个数量就是在i左侧高度小于i的高度的个数,查找完成后,我们将a[i]这个高度在树状数组中+1,表示出现过一次。

    我们再进行一次逆序枚举,即可求出在i右侧高度小于i的数量。之后我们就可以求解^的数量

    同理,我们也可以求解V的数量。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 using namespace std;
     6 typedef long long ll;
     7 const int N=200010;
     8 int n,a[N],sum[N];
     9 ll ans,l[N],r[N];
    10 inline int read() {
    11     int ret=0;
    12     int op=1;
    13     char c=getchar();
    14     while(c<'0'||c>'9') {if(c=='-') op=-1; c=getchar();}
    15     while(c<='9'&&c>='0') ret=ret*10+c-'0',c=getchar();
    16     return ret*op;
    17 }
    18 inline int lowbit(int x) {
    19     return -x&x;
    20 }
    21 inline int query(int x) {
    22     int ret=0;
    23     while(x) {
    24         ret+=sum[x];
    25         x-=lowbit(x);
    26     }
    27     return ret;
    28 }
    29 inline void add(int x) {
    30     while(x<=n) {
    31         sum[x]++;
    32         x+=lowbit(x);
    33     }
    34 }
    35 int main() {
    36     n=read();
    37     for(int i=1;i<=n;i++) a[i]=read();
    38     for(int i=1;i<=n;i++) {
    39         l[i]=query(n)-query(a[i]);
    40         add(a[i]);
    41     }
    42     memset(sum,0,sizeof(sum));
    43     for(int i=n;i>=1;i--) {
    44         r[i]=query(n)-query(a[i]);
    45         add(a[i]);
    46     }
    47     for(int i=1;i<=n;i++)
    48         ans+=(long long)l[i]*r[i];
    49     printf("%lld ",ans);
    50     ans=0;
    51     memset(sum,0,sizeof(sum));
    52     memset(l,0,sizeof(l));
    53     memset(r,0,sizeof(r));
    54     for(int i=1;i<=n;i++) {
    55         l[i]=query(a[i]-1);
    56         add(a[i]);
    57     }
    58     memset(sum,0,sizeof(sum));
    59     for(int i=n;i>=1;i--) {
    60         r[i]=query(a[i]-1);
    61         add(a[i]);
    62     }
    63     for(int i=1;i<=n;i++)
    64         ans+=(long long)l[i]*r[i];
    65     printf("%lld",ans);
    66     return 0;
    67 }
    AC Code
  • 相关阅读:
    MongoDB
    Redis主从复制
    在Flash中动画的制作方式:
    帧的类型:
    第一次做的补间动画,总结过程
    Python脚本:过滤取指定链接标题是否含有指定文字,并将其输出
    cmd命令:在ftp下载文件运行
    bat命令:在txt文本每行后加指定文字
    bat命令:在txt文本每行前加指定文字
    SSH爆破心得:
  • 原文地址:https://www.cnblogs.com/shl-blog/p/10920718.html
Copyright © 2020-2023  润新知