“浪潮杯”第九届山东省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\n",Solve());
64     }
65     return 0;
66 }
View Code

•踩坑

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

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

神评测鸡

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

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

 

posted @ 2019-06-10 11:02  HHHyacinth  阅读(323)  评论(0编辑  收藏  举报