zoukankan      html  css  js  c++  java
  • 题解报告——数列

    数列(queue)


    时间限制: 3000 ms         内存限制: 65536 KB

    【题目描述】

    一个简单的数列问题,给定一个长度为nn的数列,求这样的三个元素a1,a2,a3a1,a2,a3的个数,满足ai<aj>akai<aj>ak,且i<j<ki<j<k。

    【输入】

    第一行一个整数n(1n50000)n(1≤n≤50000)。

    接下来nn行,每行一个元素ai(0ai32767)ai(0≤ai≤32767)。

     

    【输出】

    输出一行一个整数,表示满足ai<aj>akai<aj>ak的个数。

    【输入样例】

    5
    1
    2
    3
    4
    1

    【输出样例】

    6

    【提示】

    【数据范围】

    对于30%的输入数据n200n≤200;

    对于80%的输入数据n10000n≤10000。


     

    【思路分析】

    这道题很显然是一道求逆序对的题,那么求逆序对的方法很多,最好写也是很好理解的就是归并排序,但是发现这道题用归并没思路,因为并不知道如何用归并求出每一项的逆序对个数(可能是我太菜了)所以我就写了一个线段树的逆序对,我们这里还是解释一下如何用线段树求逆序对,我们每次插入一个数之后,我们就查询这个数之后的线段树中有多少个数已经被插入了,因为在这个数之后的数一定大于这个数,并且在它之前插入,那么一定就是逆序对了,所以就实现了线段树查逆序对。

    那么了解之后,我们就可以用线段树查询了,其实发现这有3对,其实就是顺着求一遍逆序对,再反着求一遍逆序对,然后将当前数两次查到的个数相乘就可以求出以每个数为中心的3组数对了。

    【代码实现】

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<queue>
     5 using namespace std;
     6 struct sd{
     7     int l,r,num,son[2];
     8 }tree[150767];
     9 int sum=0;
    10 int root=1;
    11 const int lr=32777;
    12 long long ans;
    13 int len1[500005],len2[500005];
    14 void build(int &v,int l1,int r1)
    15 {
    16     sum++;v=sum;
    17     tree[v].l=l1,tree[v].r=r1,tree[v].num=0;
    18     if(l1==r1)
    19     {
    20         tree[v].num=0;
    21         return;
    22     }
    23     int mid=(l1+r1)/2;
    24     build(tree[v].son[0],l1,mid);
    25     build(tree[v].son[1],mid+1,r1);
    26 }
    27 int dfs(int v,int l1,int r1)
    28 {
    29     if(r1<l1) return 0;
    30     if(tree[v].l==l1&&tree[v].r==r1)
    31     return tree[v].num;
    32     int mid=(tree[v].l+tree[v].r)/2;
    33     if(r1<=mid)
    34     return dfs(tree[v].son[0],l1,r1);
    35     else
    36     if(l1>mid)
    37     return dfs(tree[v].son[1],l1,r1);
    38     else
    39     return dfs(tree[v].son[0],l1,mid)+dfs(tree[v].son[1],mid+1,r1);
    40 }
    41 void add(int key,int v,int l,int r,int orz,int id)
    42 {
    43     if(l==r&&l==key)
    44     {
    45         tree[v].num++;
    46         if(orz==1)
    47         len1[id]=dfs(1,0,l-1);
    48         else
    49         len2[id]=dfs(1,0,l-1);
    50         return;
    51     }
    52     int mid=(l+r)/2;
    53     if(key<=mid)
    54     add(key,tree[v].son[0],l,mid,orz,id);
    55     else
    56     add(key,tree[v].son[1],mid+1,r,orz,id);
    57     tree[v].num=tree[tree[v].son[0]].num+tree[tree[v].son[1]].num;
    58 }
    59 int a[500005];
    60 int main()
    61 {
    62     int n;
    63     scanf("%d",&n);
    64     build(root,0,lr);
    65     for(int i=1;i<=n;i++)
    66     {
    67         scanf("%d",&a[i]);
    68     }
    69     for(int i=1;i<=n;i++)
    70     add(a[i],1,0,lr,1,i);
    71     root=1,sum=0;
    72     build(root,0,lr);
    73     for(int i=n;i>=1;i--)
    74     {
    75         add(a[i],1,0,lr,2,i);
    76     }
    77     ans=0;
    78     for(int i=1;i<=n;i++)
    79     {
    80         ans=(ans+(len1[i]*len2[i])%mod)%mod;
    81     }
    82     printf("%lld",ans);
    83     return 0;
    84 }
  • 相关阅读:
    Trojan.DL.Agent.nxd和RootKit.Agent.yj木马清除
    Java中的格式化数值(eg:保留两位小数)
    Int16, Int32, Int64的一点感悟
    在win2003上设置asp网站
    WPF学习笔记.
    对WF工作流异常(Event on interface type for instance id cannot be delivered)的一点总结.
    创建,安装,调试 Windows Service
    灵活而又可怕的params参数数组
    (转) 输入码、区位码、国标码与机内码
    SQL Server 2008 未来将不再包含全文检索功能, 再研究此功能已经没多大意思了.
  • 原文地址:https://www.cnblogs.com/genius777/p/8653983.html
Copyright © 2011-2022 走看看