补题:Educational Codeforces Round 80 (Rated for Div. 2) E. Messenger Simulator

题目链接:https://codeforces.com/contest/1288/problem/E

题目大意:现有一个初始为1至n的序列,对这个序列进行m次操作,每次操作会给定一个数,表示把序列中的这个数挪到序列最前面的位置,原本在它之前的数字依次向后挪一个位置。要求输出每个数字最靠前的位置和最靠后的位置。

思路:

(1)先考虑简单的,如果某个数字被选中过,那么它最靠前的位置就是1,否则为它的初始位置。

(2)本题的重点在于求每个数字最靠后的位置。在一个数字被选中之前,如果他后面的数字被选中了,它的位置就会+1,由此,一个数字最靠后的位置有如下的情况(设操作序列为S,count表示统计数量,distinct表示只统计不重复的):

  1.对任意数字x,如果Si = x(1<=i<=m)并且对于任意1<=j<i有Sj != x,x可能的最靠后位置=count(distinct Sk)(1<=k<i, Sk>x)+ x

  2.对任意数字x,如果对于任意1<=i<=m有Si != x,x可能的最靠后位置=count(distinct Sk)(1<=k<=m, Sk>x)+ x

  3.对任意数字x,如果x = Si = Sj(1<=i<j<=m)并且对于任意i<k<j有Sk != x,x可能的最靠后位置=count(distinct Sk)(i<k<j)+ 1

  4.对任意数字x,如果Si = x(1<=i<=m)并且对于任意i<j<=m有Sj != x,x可能的最靠后位置=count(distinct Sk)(i<k<=m)+ 1

(3)也就是说,本题的核心在于统计某一区间内不重复元素的个数,由于n和m的数据量是3e5级别的,所以肯定不能暴力统计。此处,可以采用树状数组解决这一问题。从左至右依次处理操作序列S,对于Si,将它上次出现的位置置0(减一),位置i置1(加一)。每处理一个操作之前,计算区间和并更新该操作指定的数字的最靠后位置。

 1 #define _USE_MATH_DEFINES
 2 #include <stdio.h>
 3 #include <stdlib.h>
 4 #include <string.h>
 5 #include <string>
 6 #include <math.h>
 7 #include <ctype.h>
 8 #include <vector>
 9 #include <stack>
10 #include <map>
11 #include <set>
12 #include <algorithm>
13 #include <iostream>
14 #include <limits.h>
15 #include <iomanip>
16 #include <queue>
17 #include <functional>
18 #include<utility>
19 #define el ‘\n‘
20 #define M 1000005
21 const long double C = 0.57721566490153286060651209;
22 const long long N = 1e9+7;
23 #define ll long long
24 #define ull unsigned long long 
25 using namespace std;
26 
27 int t[300005];
28 
29 void update(int p,int x,int n)
30 {
31     while (p <= n) {
32         t[p]+=x;
33         p += p & -p;
34     }
35 }
36 
37 int query(int p)
38 {
39     int ans=0;
40     while (p) {
41         ans+=t[p];
42         p -= p & -p;
43     }
44     return ans;
45 }
46 
47 int mp[300005];
48 int Mp[300005];
49 int a[300005];
50 int ap[300005];
51 
52 int main()
53 {
54     int n,m;
55     cin>>n>>m;
56     for(int i=1;i<=n;i++){
57         mp[i]=i;
58         Mp[i]=i;
59     }
60 
61     for(int i=1;i<=m;i++){
62         cin>>a[i];
63         mp[a[i]]=1;
64         if(!ap[a[i]]){
65             update(a[i],1,n);
66             ap[a[i]]=1;
67             Mp[a[i]]+=query(n)-query(a[i]);
68         }
69     }
70     for(int i=1;i<=n;i++){
71         if(!ap[i]){
72             Mp[i]+=query(n)-query(i);
73         }
74     }
75     for(int i=1;i<=n;i++){
76         t[i]=0;
77         ap[i]=0;
78     }
79     for(int i=1;i<=m;i++){
80         Mp[a[i]]=max(Mp[a[i]],query(i)-query(ap[a[i]])+1);
81         if(ap[a[i]])update(ap[a[i]],-1,m);
82         ap[a[i]]=i;
83         update(i,1,m);
84     }
85     for(int i=1;i<=n;i++){
86         cout<<mp[i]<< ;
87         if(!ap[i])cout<<Mp[i]<<el;
88         else
89             cout<<max(Mp[i],query(m)-query(ap[i])+1)<<el;
90     }
91     return 0;
92 }

 

补题:Educational Codeforces Round 80 (Rated for Div. 2) E. Messenger Simulator

上一篇:RequestParam与RequestBody


下一篇:IfcConvertDirectionInto2D