天天看點

week12 M3

T1 瑞神的序列

題目描述

瑞神的數學一向是最好的,連強大的咕咕東都要拜倒在瑞神的數學水準之下,雖然咕咕東很苦惱,但是咕咕東拿瑞神一點辦法都沒有。

5.1期間大家都出去玩了,隻有瑞神還在孜孜不倦的學習,瑞神想到了一個序列,這個序列長度為n,也就是一共有n個數,瑞神給自己出了一個問題:數列有幾段?

段的定義是連續的相同的最長整數序列

輸入描述

輸入第一行一個整數n,表示數的個數

接下來一行n個空格隔開的整數,表示不同的數字

輸出描述

輸出一行,這個序列有多少段

樣例輸入

12

2 3 3 6 6 6 1 1 4 5 1 4

**樣例輸出 **

8

思路

記錄上一個字元,記錄不同的次數,并且注意更新上一個字元即可。

代碼

#include<iostream>
using namespace std;
int main(){
	int n;
	cin>>n;
	int ans = 0;
	int last,now;
	for(int i=0;i<n;i++){
		if(i==0){
			scanf("%d",&last);
			ans++;
		} 
		else{
			scanf("%d",&now);
			if(now!=last) ans++;
			last = now;
		}
	}
	cout<<ans<<endl;
	return 0;
}
           

T2 消消樂大師——Q老師

題目描述

Q老師是個很老實的老師,最近在積極準備考研。Q老師平時隻喜歡用Linux系統,是以Q老師的電腦上沒什麼娛樂的遊戲,是以Q老師平時除了玩Linux上的賽車遊戲SuperTuxKart之外,就是喜歡消消樂了。

遊戲在一個包含有n 行m 列的棋盤上進行,棋盤的每個格子都有一種顔色的棋子。當一行或一列上有連續三個或更多的相同顔色的棋子時,這些棋子都被消除。當有多處可以被消除時,這些地方的棋子将同時被消除。

一個棋子可能在某一行和某一列同時被消除。

由于這個遊戲是闖關制,而且有時間限制,當Q老師打開下一關時,Q老師的好哥們叫Q老師去爬泰山去了,Q老師不想輸在這一關,是以它來求助你了!!

輸入描述

輸入第一行包含兩個整數n,m,表示行數和列數

接下來n行m列,每行中數字用空格隔開,每個數字代表這個位置的棋子的顔色。數字都大于0.

輸出描述

輸出n行m列,每行中數字用空格隔開,輸出消除之後的棋盤。(如果一個方格中的棋子被消除,

則對應的方格輸出0,否則輸出棋子的顔色編号。)

**樣例輸入1 **

4 5

2 2 3 1 2

3 4 5 1 4

2 3 2 1 3

2 2 2 4 4

**樣例輸出1 **

2 2 3 0 2

3 4 5 0 4

2 3 2 0 3

0 0 0 4 4

思路

使用一個寬度為5的十字架,若滿足十字架上的連續地方數字相同,則對其進行消除即可。此題的關鍵點在于對于邊界的方格,十字架的寬度和高度就不确定了,是以采用擴充方格對周圍進行擴充,就可以直接使用十字架進行比較了。

代碼

#include<iostream>
#include<vector>
using namespace std;
int mt[40][40];
int main() {
	int n,m;
	cin>>n>>m;
	vector<pair<int,int> > v;
	for(int i=0; i<40; i++) {
		for(int j=0; j<40; j++) mt[i][j] = -1;
	}
	for(int i=0; i<n; i++) {
		for(int j=0; j<m; j++) {
			scanf("%d",&mt[i+2][j+2]);
		}
	}
	int index;
	for(int i=2; i<n+2; i++) {
		for(int j=2; j<m+2; j++) {
			int x[5],y[5];
			for(int k=0; k<5; k++) {
				x[k] = mt[i-2+k][j];
			}
			for(int k=0; k<5; k++) {
				y[k] = mt[i][j-2+k];
			}
			if(x[2]==x[0]&&x[2]==x[1]) v.push_back(pair<int,int>(i,j));
			else if(x[2]==x[3]&&x[2]==x[1]) v.push_back(pair<int,int>(i,j));
			else if(x[2]==x[3]&&x[2]==x[4]) v.push_back(pair<int,int>(i,j));
			else if(y[2]==y[0]&&y[2]==y[1]) v.push_back(pair<int,int>(i,j));
			else if(y[2]==y[3]&&y[2]==y[1]) v.push_back(pair<int,int>(i,j));
			else if(y[2]==y[3]&&y[2]==y[4]) v.push_back(pair<int,int>(i,j));
		}
	}
	for(int i=0; i<v.size(); i++) {
		int di = v[i].first,dj = v[i].second;
		mt[di][dj] = 0;
	}
	for(int i=2; i<n+1; i++) {
		for(int j=2; j<m+1; j++) {
			cout<<mt[i][j]<<" ";
		}
		cout<<mt[i][m+1]<<endl;
	}
	for(int j=2; j<m+1; j++) {
		cout<<mt[n+1][j]<<" ";
	}
	cout<<mt[n+1][m+1];
	return 0;
}
           

T4 咕咕東學英語

題目描述

咕咕東很聰明,但他最近不幸被來自宇宙的宇宙射線擊中,遭到了降智打擊,他的英語水準被歸零了!這一切的始作俑者宇宙狗卻毫不知情!

此時咕咕東碰到了一個好心人——TT,TT在吸貓之餘教咕咕東學英語。今天TT打算教咕咕東字母A和字母B,TT給了咕咕東一個隻有大寫A、B組成的序列,讓咕咕東分辨這些字母。

但是咕咕東的其他學科水準都還在,敏銳的咕咕東想出一個問題考考TT:咕咕東問TT這個字元串有多少個子串是Delicious的。

TT雖然會做這個問題,但是他吸完貓發現輝夜大小姐更新了,不想回答這個問題,并抛給了你,你能幫他解決這個問題嗎?

Delicious定義:對于一個字元串,我們認為它是Delicious的當且僅當它的每一個字元都屬于一個

大于1的回文子串中。

輸入描述

輸入第一行一個正整數n,表示字元串長度

接下來一行,一個長度為n隻由大寫字母A、B構成的字元串。

輸出描述

輸出僅一行,表示符合題目要求的子串的個數。

**樣例輸入 **

5 A

ABBB

**樣例輸出 **

6

樣例解釋

對于該樣例,符合條件的六個子串分别是:

s1-s2 s1-s4 s1-s5 s3-s4 s3-s5 s4-s5

思路

印象中是參照了某個大佬的部落格,首先從頭向後周遊,由于均有AB組成,是以找到前後不同的位置,并記錄之間的長度,然後從後向前再次周遊,使用總個數減去這些不能構成回文的子串即可,例如AAAAB這種的就不滿足,同理ABBBB也不滿足。

由于AB和BA一樣,是以需要加上一遍。

代碼

#include<iostream>
using namespace std;
string s;
char c[300000+10];
int main() {
	long long n;
	cin>>n;
	cin>>s;
	long long delta = 0; 
	long long lastIndex = 0;
	for(int i=1;i<=n;i++){
		c[i] = s.c_str()[i-1];
	}
	long long tc = 0;
	for(long long i=1;i<=n-1;i++){
		if(c[i]!=c[i+1]){
			delta += (i-lastIndex);
//			cout<<c[i]<<":"<<c[i+1]<<endl;
//			cout<<lastIndex<<endl; 
			lastIndex = i;
			tc ++;
		}
	}
	lastIndex = n+1;
	for(long long i=n;i>=2;i--){
		if(c[i]!=c[i-1]){
			delta += (lastIndex - i);
//			cout<<c[i]<<":"<<c[i+1]<<endl;
//			cout<<lastIndex<<endl; 
			lastIndex = i;
		}
	}
	cout<<(n-1)*n/2 - delta + tc<<endl;
	return 0;
}