前缀和和后缀和

1.Problem - 1791D - Codeforces

定义函数 f⁡()f() 表示字符串 x 中不同字符的数量。

现给定一个字符串 S,将它分割为两个字符串 a,b。求出:max⁡(f⁡()+f⁡())max(f(a)+f(b))。

我们可以搞一个前缀和 a 和一个后缀和 b,分别表示 f⁡(S1Si) 和 f(SiSn)。

然后枚举分界点即可。

复制代码
 1 #include <bits/stdc++.h>
 2 #define re register
 3 
 4 using namespace std;
 5 
 6 const int N = 2e5 + 10,M = 230;
 7 int T,n;
 8 int arr[N],brr[N];
 9 string s;
10 bool vis[M];
11 
12 int main(){
13     cin >> T;
14     while (T--){
15         int ans = 0;
16         memset(arr,0,sizeof(arr));
17         memset(brr,0,sizeof(brr));
18         memset(vis,false,sizeof(vis));
19         cin >> n >> s;
20         s = ' ' + s;
21         for (re int i = 1;i <= n;i++){//前缀和 
22             if (!vis[s[i]]){
23                 arr[i] = arr[i - 1] + 1;
24                 vis[s[i]] = true;
25             }
26             else arr[i] = arr[i - 1];
27         }
28         memset(vis,false,sizeof(vis));
29         for (re int i = n;i;i--){//后缀和 
30             if (!vis[s[i]]){
31                 brr[i] = brr[i + 1] + 1;
32                 vis[s[i]] = true;
33             }
34             else brr[i] = brr[i + 1];
35         }
36         for (re int i = 0;i <= n;i++) ans = max(ans,arr[i] + brr[i + 1]);//选出 max 
37         printf("%d\n",ans);
38     }
39     return 0;
40 }
View Code
复制代码

 2.Problem - B - Codeforces 利用pair分别存储数组的值和下标,然后对值进行排序,对每一个a[i],最多有i - 1个

我们可以通过前缀和来根据题目的条件来判断,只有当前前缀和大于该a[i]时才满足条件,指针++,否则输出当前前缀和

的个数 - 1。

复制代码
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long 
 4 #define cy cout << "Yes" << endl
 5 #define cn cout << "No" << endl
 6 
 7 const int N = 1e6 + 10,inf = 1e9;
 8 const int mode = 1e9 + 7;
 9 ll j,k,n,m,t;
10 ll a[N],p[N],id[N],res[N];
11  
12 int main(){
13     cin>>t;
14     while(t--){
15         cin>>n;
16         vector<pair<ll,ll> > v;
17         for(ll i=1;i<=n;i++){
18             cin>>k;
19             v.push_back({k,i});
20             res[i]=0;
21         }
22         sort(v.begin(),v.end()); n=0;
23         
24         for(auto [x,y]:v){
25             n++;
26             a[n]=x; 
27             id[n]=y;
28         }
29         
30         for(ll i=1;i<=n;i++)p[i]=p[i-1]+a[i];
31         j=1;
32         for(ll i=1;i<=n;i++){
33             j=max(j,i);
34             while(j<n){
35                 if(a[j+1]>p[j]){
36                     break;
37                 }
38                 j++;
39             }
40             res[id[i]]=j-1;
41         }
42         for(ll i=1;i<=n;i++){
43             cout<<res[i]<<' ';
44         }
45         cout<<'\n';
46     }
47 }
Code
复制代码

 3.Problem - 1352E - Codeforces

某一段连续的和想到用前缀和,我们可以用双指针来表示两个前缀和的差值。

将这个数组里的数都放进一个桶里。然后枚举区间的左右端点,答案累加为这个区间和的数的个数。有两个点需要注意:

  1. 判断区间和是否超过n(因为区间里的数都在n以内),否则要么RE,要么炸空间。

  2. 一次累加桶里的某个数后,要记得将桶里的这个数的个数清00,否则会重复算。代码如下:

    复制代码
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define endl '\n'
     4 #define ll long long
     5 #define cy cout << "YES" << endl
     6 #define cn cout << "NO" << endl
     7 int _,n,m;
     8 const int N = 1e3 + 10,inf = 1e9;
     9 const int mod = 1e9 + 7;
    10 int a[N],s[N],t[N];
    11 
    12 int main()
    13 {
    14     cin >> _;
    15     while(_ -- )
    16     {
    17         memset(s, 0, sizeof s);
    18         memset(t, 0, sizeof t);
    19         cin >> n;
    20         for (int i = 1; i <= n; i ++ ) cin >> a[i],s[i] = s[i - 1] + a[i],t[a[i]] ++;
    21         
    22         int ans = 0;
    23         for (int i = 0; i <= n; i ++ ){
    24             for (int j = i + 2; j <= n; j ++ )
    25                 if(s[j] - s[i] <= n)
    26                 {
    27                     ans += t[s[j] - s[i]];
    28                     t[s[j] - s[i]] = 0;
    29                 }
    30                 else break;
    31         }
    32         cout << ans << endl;
    33     }
    34 }
    Code
    复制代码

     

4.Problem - 1692G - Codeforces 这道题目转换一下题意就是当a[i] < 2 * a[i + 1]的时候满足条件

我们可以把满足这两个条件的a[i]转换为b[i] = 1,否则b[i] = 0,然后构造出来一个长度为n -1 的数组,在这个数组中我们只需要找到

长度k和由k个1组成的子序列,然后动态滑动窗口维护这个区间的值,当其等于k的时候,满足条件的区间数量 + 1

复制代码
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define endl '\n'
 4 #define ll long long
 5 #define cy cout << "YES" << endl
 6 #define cn cout << "NO" << endl
 7 #define c1 cout << -1 << endl
 8 
 9 int _,n,k;
10 const int N = 2e5 + 10,inf = 1e9;
11 const int mod = 1e9 + 7;
12 int a[N];
13 
14 
15 int main()
16 {
17     cin >> _;
18     while(_ -- ){
19         cin >> n >> k;
20         for (int i = 1; i <= n; i ++ ) cin >> a[i];
21         
22         int b[n];
23         for (int i = 1; i < n; i ++ ){ //将满足条件的a[i]转换为b[i]
24             if(a[i] < 2 * a[i + 1]) b[i] = 1;
25             else b[i] = 0;
26         }
27         
28         int ans = 0;
29         for (int i = 1; i <= k; i ++ )
30             ans += b[i];
31             
32         int res = 0;
33         if(ans == k) res ++;
34         for (int i = k + 1; i < n; i ++ ){ //滑动窗口动态维护长度为K的区间,然后判断这个区间内的值是否为k
35             ans += b[i];
36             ans -= b[i - k];
37             if(ans == k) res ++;
38         }
39         
40         cout << res << endl;
41     }
42     return 0;
43 }
Code
复制代码

 

posted @   rw156  阅读(64)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)

阅读目录(Content)

此页目录为空

点击右上角即可分享
微信分享提示