P9753 [CSP-S 2023] 消消乐 题解

不用栈也不用map。

考虑预处理。 处理 a 数组,每次走到一个位置 i,往前搜索。 当前位置不等于 i 则通过这个位置继续往前查找。一直到当前位置等于 i,或者到达最前端则停止。 接下来进行第二次处理。 由于已经对 a 进行过预处理,在计算时只需要从有值的点分别往前统计即可。 最后求一遍和。 

感谢学弟 @kibi 的优化!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2000010;
int n, a[N], f[N],tot;
char s[N];
signed main() {
    memset(a, -1, sizeof a);
    cin>>n;
    for(int i=1;i<=n;i++) cin>>s[i];
    for(int i=1;i<=n;i++) a[i]=i-1;
    for(int i=1;i<=n;i++){
        while(s[a[i]]!=s[i])
        {
            a[i]=a[a[i]]-1;
            if(a[i]<=-1) break;
        }
    }
  //  for(int i=1;i<=n;i++) cout<<a[i]<<' ';
  //  cout<<endl;
    for(int i=1;i<=n;i++) {
        if(a[i]>0) f[i]=f[a[i]-1]+1;
    }
    for(int i=1;i<=n;i++) {
        tot+=f[i];
    }
    cout<<tot<<endl;
}

  

  

加强版:CF1223F Stack Exterminable Arrays - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

 

直接使用上面的思路,发现前四个点跑得飞快,但tle on #5。


考虑在上面的思路的基础上进行剪枝。

观察每一次往回预处理上一个出现位置的情况。

若查找位置已经小于当前这个数字最早出现的坐标,此时可以将这个值改为-1然后break。

 

这样就少了很多重复查询的过程,不容易被卡到 O(n2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 300010;
int n, a[N], f[N],tot;
int s[N];
int t;
int vis[N];
signed main() {
    memset(vis, 0x3f3f3f3f, sizeof vis);
    memset(a,-1,sizeof a);
    cin>>t;
    while(t--)
    {
        tot=0;
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>s[i],f[i]=0;
            vis[s[i]]=min(vis[s[i]],i);
        }
        f[0]=0;
        for(int i=1;i<=n;i++) a[i]=i-1;
         
        for(int i=1;i<=n;i++){
            while(s[a[i]]!=s[i])
            {
                a[i]=a[a[i]]-1;
                if(a[i]<=-1) break;
                if(vis[s[i]]>a[i]){
                    a[i]=-1;
                    break;
                }
            }
        }
         
        for(int i=1;i<=n;i++) {
            if(a[i]>0) f[i]=f[a[i]-1]+1;
        }
         
        for(int i=1;i<=n;i++) {
            tot+=f[i];
        }
         
        cout<<tot<<endl;
    }
     
}

  

posted @   Miya555  阅读(248)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示
主题色彩