Codeforces Round #450 (Div. 2)(思维+树状数组)

  题意:若数组中一个数前的所有数都比这个数小,那么定义它为一个record。若去掉某一个元素使剩下的数组中record最多,求这个元素

  分析:对每个元素,考虑去掉它的情况。若第i个元素前有i-1个小于它的元素,则去掉该元素后这个数组前i个元素的record总数-1.若第i个元素前有i-2个小于它的元素,那么去掉前i个元素中大于第i个元素的那个元素后,前i个元素的record总数+1.若第i个元素前有两个及以上的元素大于它,那么无论去掉它还是大于它的元素,前i个元素record总数不变。循环完毕后找到去掉它后record总数增加最多的元素即可。

  实现:用树状数组实现快速查询小于某元素的元素个数,用STL的set(红黑树)的lower_bound实现快速找到大于某元素的最小元素。

AC代码:

 1 #include <iostream>
 2 #include<algorithm>
 3 #include<set>
 4 #define MAXN 100005
 5 using namespace std;
 6 bool r[MAXN];//表示初始时第i个元素是否为record
 7 int a[MAXN];//输入的数据
 8 int x[MAXN];//移去值为i的元素后record总数的变化
 9 int tree[MAXN];//树状数组
10 int n;
11 set<int> s;
12 
13 void add(int i,int num)
14 {
15     for(int j=i;j<=n;j+=j&-j) tree[j]+=num;
16 }
17 
18 int Sum(int i)
19 {
20     int result=0;
21     for(int j=i;j>0;j-=j&-j)result+=tree[j];
22     return result;
23 }
24 
25 int main()
26 {
27     cin>>n;
28     for(int i=1;i<=n;++i)
29     {
30         cin>>a[i];
31         if((Sum(a[i]-1)==i-1))
32         {
33             x[a[i]]--;
34         }
35         else if((Sum(a[i]-1)==i-2))
36         {
37             x[*(s.lower_bound(a[i]))]++;
38         }
39         s.insert(a[i]);
40         add(a[i],1);
41     }
42     int ri=1,rmax=x[ri];
43     for(int i=1;i<=n;++i)
44     {
45         if(x[i]>rmax)
46         {
47             ri=i;
48             rmax=x[i];
49         }
50     }
51     cout<<ri<<endl;
52 }

结论

秒啊,学不会…

猜你喜欢

转载自blog.csdn.net/calculate23/article/details/87718395