• “浪潮杯”第九届山东省ACM大学生程序设计竞赛(重现赛)E.sequence(树状数组求逆序对(划掉))


    传送门

    E.sequence

    题意

      定义序列 p 中的 "good",只要 i 之前存在 pj < pi,那么,pi就是 "good";

      求删除一个数,使得序列中 "good" 的个数最多;

    题解

      一个数 pi 对 "good" 的贡献有两个来源:

      ①p本身为"good",对答案的贡献为 1;

      ②删除 p后,i 之后的本来是 "good" 的数因为 pi 被删除而变成非 "good" 数,这样的数有多少个,pi对答案的贡献就是多少;

      贡献①好求,主要是贡献②的求解方法;

      定义 fir,sec 为第一小,第二小的数;

      枚举位置 i,判断 pi 与 fir,sec 的大小关系;

      ①如果 pi > min{fir,sec},那么 pi 本身就为 "good";

      (1)如果 pi > sec,删除其之前的任何一个数,都不会使 pi 由 "good" 变为 非 "good";

      (2)如果 fir > pi > sec,那么,删除 fir 会使得 pi 由 "good" 变为 非"good";

      ②pi < min{fir,sec},pi 本身对答案无贡献;

    AC代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 #define INF 0x3f3f3f3f
     5 #define lowbit(x) (x&-x)
     6 #define mem(a,b) memset(a,b,sizeof(a))
     7 const int maxn=1e6+50;
     8  
     9 int n;
    10 int p[maxn];
    11 int a[maxn];///a[i]:判断p[i]对答案的影响
    12  
    13 int Solve()
    14 {
    15     int fir=INF;
    16     int sir=INF;
    17     for(int i=1;i <= n;i++)
    18     {
    19         if(p[i] > fir)
    20         {
    21             a[p[i]]++;
    22             if(p[i] < sir)
    23                 a[fir]++;
    24         }
    25  
    26         if(p[i] < fir)
    27         {
    28             sir=fir;
    29             fir=p[i];
    30         }
    31         else if(p[i] < sir)
    32             sir=p[i];
    33     }
    34     
    35     int ans;
    36     int ansTot=n+1;
    37     for(int i=1;i <= n;++i)
    38     {
    39         int cur=a[p[i]];
    40         if(ansTot > cur)
    41         {
    42             ans=p[i];
    43             ansTot=cur;
    44         }
    45         else if(ansTot == cur && ans > p[i])
    46             ans=p[i];
    47     }
    48     return ans;
    49 }
    50 int main()
    51 {
    52 //    freopen("C:\Users\hyacinthLJP\Desktop\in&&out\contest","r",stdin);
    53     int test;
    54     scanf("%d",&test);
    55     while(test--)
    56     {
    57         scanf("%d",&n);
    58         for(int i=1;i <= n;i++)
    59         {
    60             scanf("%d",p+i);
    61             a[i]=0;
    62         }
    63         printf("%d
    ",Solve());
    64     }
    65     return 0;
    66 }
    View Code

    •踩坑

      刚开始判断其本身的影响和对其他的数的影响时,用的是树状数组求逆序对判断的(TLE到死);

      其实完全没必要记录这么多信息,只需记录某数前的第一小和第二小的数即可;

    神评测鸡

      用之前AC的代码,Ctrl+C , Ctrl+V,TLE???

      AC之前用的是 ++i,一直TLE,改成 i++,AC???

  • 相关阅读:
    Django中前端界面实现级联查询
    二叉树遍历规则
    计算机组成原理面试总结
    用python介绍4种常用的单链表翻转的方法
    跨域资源共享(CORS)
    python中单例模式的四种实现方式
    算法和数据结构
    手写配置文件实现两套配置文件的切换
    CentOS 7 安装教程
    配置管理系统
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/10996561.html
Copyright © 2020-2023  润新知