首页 > 其他分享 >CSP-S 2023 消消乐-题解

CSP-S 2023 消消乐-题解

时间:2023-10-23 11:26:23浏览次数:34  
标签:const int 题解 2023 字符串 Hash include CSP 消除

CSP-S 2023 消消乐-题解

闲话

省流:long long 模拟pair

好抽象的题,可惜考场上没做出来。感觉其实是一个挺有趣的题的。

题目描述

小 L 现在在玩一个低配版本的消消乐,该版本的游戏是一维的,一次也只能消除两 个相邻的元素。 现在,他有一个长度为 \(n\) 且仅由小写字母构成的字符串。我们称一个字符串是可消 除的,当且仅当可以对这个字符串进行若干次操作,使之成为一个空字符串。 其中每次操作可以从字符串中删除两个相邻的相同字符,操作后剩余字符串会拼接 在一起。 小 L 想知道,这个字符串的所有非空连续子串中,有多少个是可消除的。

题目分析

首先有一个很显而易见的\(O(n^2)\)的暴力

(考场上只打了这个暴力)

我们只用枚举每一个区间判断它是否可以删除即可,我们可以简单分析得知,一个字符只要能被消除,它就应该消除,留给后面的字符来消除一定不会比能消除就消除更优秀。

所以我们直接枚举每一个点作为消除的起点,用一个栈来统计,如果当前点即将入栈的字符与栈顶元素相同,那么就直接弹栈,否则将当前字符入栈。

那么我们只需要每次判断栈是否为空就可以了,如果当前栈为空,那么答案就可以累加\(1\),否则就进行下一次操作。

关键代码

void Subtask_1(){
	S.GTop=0;
	for(int i=1;i<=n;i++){
		while(!S.Empty()) S.Pop();
		for(int j=i;j<=n;j++){
			if(S.Top()==In[j]&&!S.Empty()) S.Pop();
			else S.Push(j);
			if(S.Empty()) Ans++;
		}
	}
	printf("%lld",Ans);
}

期望得分:\(50Pts\)

然后对这个出入栈的思想进行优化

首先我们想这个题的数据范围是\(2\times 10^6\)的,那么一定可以用\(O(n)\)的做法,所以我们尝试只以\(1\)为起点,来统计答案。

思考什么情况下一段区间可以视为可消除的。如果从\(1\)开始向栈中插入元素的话,那么一段区间是可消除的,当且仅当插入这段区间前后栈中元素的状态相同。

所以得到这个结论之后,我们可以用一个Hash值来记录栈中元素的状态,然后记录每个状态的出现次数\(Time_i\),那么答案即为:\(\sum ^{Total}_{i=1}Time_i\times (Time_i-1)/2\),因为对于每个状态都可以两两配对,随意组合即可。而对于这个式子,更快捷的方法是在每次出现一个状态时,就将答案累加这个状态之前出现的次数。

但是因为unordered_map不能套pair,所以我用的long long把两个Hash值合在一起。(这里用双Hash是为了防止撞Hash值)

Code

/*
 * @Author: Ehundategh
 * @Date: 2023-10-23 09:27:47
 * @FilePath: \Code\LuieGu\CF1223F.cpp
 * @Description: You Steal,I kill
 */
#include <unordered_map>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 2000100
const int p=20070903;
const int Inv1=674759451;
const int Mod1=999911659;
const int Inv2=489437524;
const int Mod2=1e9+7;
using namespace std;
inline int Calc1(int a,int b){return ((a+=b)>Mod1)?a-Mod1:a;}
inline int Del1(int a,int b){return ((a-=b)<0)?a+Mod1:a;}
inline int Mul1(int a,int b){return 1ll*a*b%Mod1;}
inline int Calc2(int a,int b){return ((a+=b)>Mod2)?a-Mod2:a;}
inline int Del2(int a,int b){return ((a-=b)<0)?a+Mod2:a;}
inline int Mul2(int a,int b){return 1ll*a*b%Mod2;}
char S[MAXN];
int n;
long long Ans=0;
class Stack{
private:
    int STop=0;
    int Pos[MAXN];
    int Hash1=0,Hash2=0;
public:
    void Push(int a){
        Hash1=Mul1(p,Hash1); Hash1=Calc1(Hash1,S[a]); 
        Hash2=Mul2(p,Hash2); Hash2=Calc2(Hash2,S[a]); 
        Pos[++STop]=a;
    }
    void Pop(){
        Hash1=Del1(Hash1,S[Pos[STop]]); Hash1=Mul1(Hash1,Inv1); 
        Hash2=Del2(Hash2,S[Pos[STop]]); Hash2=Mul2(Hash2,Inv2); 
        --STop;
    }
    char Top(){return S[Pos[STop]];}
    long long Get(){return ((long long)Hash1<<32ll)+(long long)Hash2;}
}St;
unordered_map<long long,int> Map;
int main(){
    scanf("%d",&n);
    Ans=0;
    Map[0]=1;
    for(int i=1;i<=n;i++){
        if(St.Top()==S[i]) St.Pop();
        else St.Push(i);
        Ans+=Map[St.Get()];
        Map[St.Get()]++;
    }
    printf("%lld\n",Ans);
}

标签:const,int,题解,2023,字符串,Hash,include,CSP,消除
From: https://www.cnblogs.com/Ehundategh/p/17781973.html

相关文章

  • 「Temp」CSP-S 2023 JL 迷惑代码大赏
    (欢迎投稿。)在\(213\)份代码中共查找到\(21\)个//freopen,来自JL-S00031、JL-S00045、JL-S00047、JL-S00085、JL-S00123、JL-S00150、JL-S00157、JL-S00167八位选手。查找到\(15\)份114514。查找到\(10\)份.ans。《虚空索敌人》JL-S00089最离谱的是他w和r写反了......
  • CF1839A题解
    分析可以很容易地想到如果只有1要求的话答案就是\(\lceil\frac{n}{k}\rceil\)。最优策略显然是在每个整除分块的第一位放一个1。思考加入2条件如何修改。显然当最后一块的大小不为1时,大于1的部分后缀和为0。所以需要在最后一位加入一个1。所以答案为\(\begin{cases}\lc......
  • CSP-S 2023游记
    CSP-S2023游记Day-1考前一天集训。快下课的时候全机房一起用SPFA写全源最短路,然后我一个手残在SLF的时候写了一个dis[q.front()]<dis[v]而我的dis是一个二维数组,然后就变成了比较地址,竟然还把最卡我们的那个点跑过去了,神秘。Day0没啥事干,父亲大人上班没把电脑带回......
  • CSP-S 2023复赛游记
    Day-?得知了自己初赛的分,58分,不算很高,但是能进复赛了,感觉有点低落,毕竟有点低。然后想了想又不低落了,至少19年我因为只报了普及没得考(不过就算报了初赛过了也可能连格雷码都做不出来)。Day-2大家决定举办手速杯,这是好的。但是赛题是LCT板子,这是坏的。然后就和猫和bot协......
  • 2023 CSP-J/S 第二轮游记
    是少见的两场都参加的蒟蒻捏~( ̄▽ ̄)~*10.20比赛前一天,上午最后一节课跑完速耐之后吃不下一点饭,去小卖部买了瓶喝的就直接去机房了。和wwm_大佬讨论了一会儿吃饭的事,估计是我说我中午没吃饭的事被教练听到了,教练到机房之后直接问我是不是没吃饭然后塞给了我一个面包和一个橘子(......
  • [ZJOI2015] 地震后的幻想乡积分题解
    题意:给定一个无向图,边权为\([0,1]\)之间的随机变量。求图最小生成树最大边权的期望。\(n\le10\)。Soluion:Meatherm口诏:我都不知道这个东西怎么想出来的针对这道题,好像正常的方法是转计数然后斯特林反演+dp。但是如果想到概率理论,你就已经赢了很遗憾,我没想出来设最大边......
  • 2023年秦皇岛CCPC赛后总结zzh
    g题签到,看了一下题意,直接a了。接着一起看j去了,j题读了下题,感觉是一个板子题,但那个类型的题好久没写了,带的板子上也没有,我在想的时候,lhy说想打个暴力试试,结果暴力就直接过了。。。接着是a,构造题,喔一开始想了个循环结,感觉没错误,wa了几发后突然发现这个做法错的很离谱,罚时爆炸。最后z......
  • 2023.10.18
    第18节:调试这一节强调了调试的重要性以及一些有关调试的心理学和技巧。1.调试的目标是解决问题,而不是对问题提出攻击性的反应。遇到bug时,应以解决问题为导向,而不是责怪他人或自己。2.当你目睹bug的发生或看到bug报告时,不要急于表示“那不可能”。首要任务是思考为什么......
  • 2023.10.19
    1.0版本生成四则运算并存入数据库importjavax.servlet.ServletException;importjavax.servlet.annotation.WebServlet;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.io.IOE......
  • 2023.10.20
    四则运算2.0失败版本server.port=8080spring.datasource.url=jdbc:h2:mem:testedspring.datasource.driverClassName=org.h2.Driverspring.datasource.username=saspring.datasource.password=passwordspring.jpa.hibernate.ddl-auto=updatepackagecom.example.mathquiz;//替换......