首页 > 代码库 > 【洛谷P1371】NOI元丹

【洛谷P1371】NOI元丹

不考虑insert

则NOI的个数可通过O(n)递推得到:

sum_NOI<--sum_NO<--sum_N

考虑insert:

首先预处理对于每个N,其后面的O和I各有多少个

N:显然插入在最前面

I:最后面

O:枚举断点,前面的N*后面的I,取max

技术分享
 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 #define ll long long
 5 const int L=100100;
 6 int n,nn,ii,oo;
 7 ll ans,sum_N,sum_NO,sum_NOI;
 8 char s[L];
 9 struct fax{
10     int loc,o,i;//loc???°μ? O£???oóμ? I  
11 }N[L];
12 struct fbx{
13     int loc,i;//loc??oóμ? I  
14 }O[L];
15 ll max(ll x,ll y){
16     return x>y?x:y;
17 }
18 void addN(){
19     ll n0=0;
20     for (int j=1;j<=oo;j++)
21         n0+=O[j].i;
22     ans=max(ans,sum_NOI+n0);
23 }
24 void addI(){
25     ll ooo,i0=0;
26     for (int i=1;i<=nn;i++){
27         ooo=N[i].o;
28         i0+=oo-ooo;
29     }
30     ans=max(ans,sum_NOI+i0);
31 }
32 void addO(){
33     ll o0=0;
34     for (int j=1;j<=nn;j++)
35         o0=max(o0,(ll)j*N[j].i);
36     ans=max(ans,sum_NOI+o0);
37 }
38 int main(){
39     sum_N=sum_NO=sum_NOI=ii=oo=nn=ans=0;
40     scanf("%d",&n);
41     scanf("%s",s);
42     for (int i=0;i<n;i++){
43         if (s[i]==N){
44             nn++;
45             N[nn].loc=i; 
46             N[nn].o=oo;
47             N[nn].i=ii;
48             sum_N++;
49         }
50         if (s[i]==O){
51             oo++;
52             O[oo].loc=i;
53             O[oo].i=ii;
54             sum_NO+=sum_N;
55         }
56         if (s[i]==I){
57             ii++;
58             sum_NOI+=sum_NO;
59         }
60     }
61     for (int j=1;j<=nn;j++)
62         N[j].i=ii-N[j].i;
63     for (int j=1;j<=oo;j++)
64         O[j].i=ii-O[j].i;
65     addN();
66     addO();
67     addI();
68     printf("%lld",ans);
69     return 0;
70 }
STD

 

【洛谷P1371】NOI元丹