zoukankan      html  css  js  c++  java
  • 2014 UESTC Training for Data Structures E

    E - 休生伤杜景死惊开

    Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
     

    陆伯言军陷八卦阵之中,分明只是一条直路,却怎的也走不到尽头。阵中尽是石堆,以某一石堆为参考,无论向走还是向右,总是会回到出发的石堆,最后幸得一黄姓老翁带路才得脱出。

    陆伯言逃离八卦阵后,来到山顶观察此阵,记从左往右第i堆石堆的高度为Ai,发现任何两堆较矮的石堆都能和它们之间的一座较高的石堆形成"八卦锁",将其中之人牢牢锁住,无从逃脱。

    根据石堆的情况,陆伯言大致计算了“八卦锁”的数量(即 Ai<Aj>Ak,i<j<k 的组合数),不禁心中一惊,对孔明惊为天人,遂放弃追击,收兵回吴。

    “有劳岳父了。” “为何将其放走?” “...一表人才,何必浪费于此。”

    Input

    第一行一个整数n,表示石堆堆数。

    接下来一行,n个整数,第i个数表示从左到右第i堆石堆的高度Ai

    1n50000,1Ai32768

    Output

    一个整数,“八阵锁”的数目。

    Sample input and output

    Sample InputSample Output
    5
    1 2 3 4 1
    6

    这是一道好玩的题,题意是求Ai<Aj>Ak,i<j<k 的组合数,其实可以用归并排序来求顺序对,再反过来求顺序对,然后对应位置相乘即可,而由于学了树状数组,于是就决定用树状数组来写,假设x[i]是数值为i的数的个数,所以求的比q[i]小的数就有x[i-1]+x[i-2]+…..+x[2]+x[1],于是就可以用树状数组来写了,从头到尾扫一遍,对每个数都算一下前面比他小的数的个数即x[q[i]-1]+x[q[i]-2]+…….x[2]+x[1],然后从后往前扫一遍,对每个数计算后面比他小的数的数量。然后相同位置计算得到的两个数相乘,再求和就可以了。

     

    这道题有个坑,求和后的数有可能超过int,而对于C++来说整型越界不会报错,然后居然在text1 WA了,我还一直以为是有一组奇葩数据,改了好久都该不好。

    根本就没有检查ans,一直在算法那里对照树状数组的标程。。。。。

    最后再看题目时在想题目是不是数据范围给小了,结果灵机一动想到ans有可能超过int,于是longlong一改,就AC了。

    #include <iostream>
    #include<stdio.h>
    #include<cstring>
    using namespace std;
    int q[100005]={},ll[100005]={},rr[100005]={},tree[330000]={},n,maxn;
    void jia(int j)
    {
        while (j<=maxn){
            tree[j]+=1;
            j+=j&-j;
        }
    }
    int suan(int j)
    {
        int ans=0;
        while (j>0){
            ans+=tree[j];
            j-=j&-j;
        }
        return ans;
    }
    int main()
    {
        int j;
        cin>>n;
        maxn=0;
        for (j=1;j<=n;j++){
            scanf("%d",&q[j]);
            q[j]++;
            if (q[j]>maxn) maxn=q[j];
        }
        for (j=1;j<=n;j++){
            jia(q[j]);
            ll[j]=suan(q[j]-1);
        }
        memset(tree,0,sizeof(tree));
        for (j=n;j>0;j--){
            jia(q[j]);
            rr[j]=suan(q[j]-1);
        }
        long long ans=0;
        for (j=1;j<=n;j++) ans+=rr[j]*ll[j];
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    Java SE (3) 之 事件监听
    Java SE (2)之 Graphics 画图工具
    Java SE (1)之 JFrame 组件 GridLayout布局
    解决IIS7中出现An error occurred on the server when processing the URL错误提示的方法
    VS2010中配置C#Project不生成.vhost.exe和.pdb文件的方法
    IIS7和IIS7.5备份和还原的方法
    C# 读取IE缓存文件(2)
    C# 读取IE缓存文件(1)
    raywenderlich的Swift编程风格指南
    Swift和C#的基本语法对比
  • 原文地址:https://www.cnblogs.com/Atlantis67/p/3702428.html
Copyright © 2011-2022 走看看