7.10学习内容+题目解析详解(普及)

作者:单均浩

学习内容(复赛):(全部自己总结)

学习内容(初赛):(全部自己总结)

必做题题目解析+关键代码

T1 字串计算

题目描述

给出一个只包含0和1的字符串(长度在1到100之间),求其每一个子串出现的次数。

输入格式

一行,一个01字符串。

输出格式

对所有出现次数在1次以上的子串,输出该子串及出现次数,中间用单个空格隔开。
按子串的字典序从小到大依次输出,每行一个。

题目解析

考虑map,定义一个map,用string映射int
开始枚举,用substr取每个字符串,O(n2)
用map遍历,大于一的输出,O(n)

关键代码


T2 小信反转串

题目描述:

小信有一个长为 n 的只含 0 和 1字符串 s。 他可以进行最多 k 次如下操作:

选择字符串 s 的一个子串,将其中的字符反转(0 变成 1,1 变成 0)。

求在操作过程中(操作数可为0)出现过的最长的连续的 1 的长度。

输入格式:

第一行,2 个正整数 n,k; 第二行,字符串 s。

输出格式:

输出不超过 k 次操作后,最长的连续的 1 的长度。

题目解析

关键代码

image

T3 卡牌

题目描述:

小信有很多组卡牌,每组卡牌的形式像这样,x,x+1,x+2,…,x+m−1,x是这组卡牌的第一张数值,m是这组卡牌的长度。

但有一天他不小心把所有卡牌搞混在了一起。比如他一开始有两组卡牌[2,3,4,5]和[3,4],混在一起之后变成了[3,3,4,5,4,2]。

给定搞混后的卡牌,问你小信最初最少有多少组卡牌。

输入格式:

第一行包含一个整数 T,表示测试数据组数。

对于每组测试数据,第一行一个整数 n,代表所有卡牌混在一起后的总长度。

第二行n个整数,a1,a2,…,an,代表混合后的卡牌序列。

输出格式:

对于每组测试数据,输出一个整数表示最初最少有多少组卡牌。

题目解析

multiset+暴力枚举走天下 O(n)
注意T组数据

while (!s.empty()){
	int x=*s.begin();
	s.erase(s.find(x));
	x++;
	while (s.count(x)!=0){
		s.erase(s.find(x));
		x++;
	}
	ans++;
}

T4 简单的求和

题目描述:

给定一个长度为 n 的数组a 和 k,小信想知道数组中有多少对数相加等于 k 。

输入格式:

第一行包含两个整数 n,k。

第二行 n 个整数 ai。

输出格式:

输出一个整数表示有多少对。

题目解析
Sort排序一遍 O(nlongn)
尺取法一遍(上课例题参考)O(n)

while (l<r){
        if (a[l]+a[r]==k){
        	if (a[l]==a[r]){        		
				long long t=r-l+1;
        		sum=sum+t*(t-1)/2;
        		break;
			}
			else{
				long long tl=1,tr=1;
				while (a[l]==a[l+1]){
					tl++;
					l++;
				}
				l++;
				while (a[r]==a[r-1]){
					tr++;
					r--;
				}
				r--;
				sum=sum+tl*tr;
			}    
        }
        else if (a[l]+a[r]>k){
        	--r;
		}
        else{
        	++l;
		}
    }

T5 数位和问题

题目描述:

数位之和的意思是某个整数每一位之和。比如123的数位之和就是6。

小信现在给你一个长度为 n 的数组 a ,然后操作 q 次,有两种操作:

1 l r 代表将下标范围在 [l,r] 内所有的 ai , 修改为 ai 的数位之和

2 x 代表输出ax 。

输入格式:

第一行两个整数 n, q,

第二行包括 n 个 整数,a1,a2,…,an。

接下来q 行,每行代表一次操作。

输出格式:

对于每次操作2,输出一个整数表示答案。

题目解析

如果你直接暴力,就会……

void f(int x){
	int cnt=0,m=a[x];
	while(m!=0){
		cnt+=m%10;
		m/=10;
	}
	a[x]=cnt;
}

接着,我们就会用到上课学过的神奇的STL之——set!!!
因为这道题数位和操作只需进行几次就可,用set记录需要数位和操作的数的下标,再通过一些奇奇怪怪的操作干一些奇奇怪怪的事情(lower_bound,upper_bound,auto……)
总而言之,就是用set优化

            int c[1000001],p=0;	
			auto st=s.lower_bound(l);
			auto en=s.upper_bound(r);
			for(auto it=st;it!=en;++it){
				f(*it);
				if (a[*it]<10){
					c[++p]=*it;
				}
			}
			for(int i=1;i<=p;++i){
				s.erase(c[i]);
			}

T6 排队

题目描述:

幼儿园里的小朋友在玩排队游戏,他们会根据老师的要求排队。

老师共进行 n 次操作,操作分为以下三种:
1 x : 将一名身高为 x 的小朋友加入队尾
2 : 输出队列最前面的小朋友的身高,并让他出队列,保证进行该操作时队列非空
3 : 将队列里的小朋友按照身高升序排序
输入格式:
第一行,包含一个正整数 n,表示操作次数。
加下来n行按照以下格式之一输入操作:
1 x
2
3
输出格式:
对应操作进行输出。

题目解析

关键代码

        if (op==1){
			int x;
			scanf("%d",&x);
			q.push(x);
		}
		if (op==2){
			if (!q2.empty()){
				printf("%d\n",q2.top());
				q2.pop();
			}
			else{
				printf("%d\n",q.front());
				q.pop();
			}
		}
		if (op==3){
			while(!q.empty()){
				q2.push(q.front());
				q.pop();
			}
		}

轻喷!!!

8 个赞