ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2022高考集训1

2022-08-17 19:01:22  阅读:151  来源: 互联网

标签:Istrue int 高考 register long 2022 MAX include 集训


别问为什么6.6的考试今天才来写总结

成绩


反正就是很拉跨

T1

模拟题,按照题意模拟 \(IP\) 地址即可。

题目已经保证了只有四个被分割的自然数,就没必要去想哪些数可以合并,哪些数需要拆开了。

注意:

  • 遇到非法字符直接删除。
  • 数字大于 \(255\) 的改为 \(255\)。
  • 数字中不能有前导零。

其他的就需要注意一下分隔符的输出和最后一位上合法的零就行了。

赛后隔壁机房的本来想把 \(int\) 卡掉的,但是未遂。不过我因为没有读最后一位上的合法零成功挂掉了⑨分。

Code

#include<cstdio>
#include<cstring>

using namespace std;

const int MAX = 40;
int len, cnt_num, cnt_pos;
long long num;
long long nums[MAX], pos[MAX];
char s[MAX];
bool Istrue = true;

inline bool Number(char ch){
	return ch >= '0' && ch <= '9' ? true : false;
}
//想了半天不可能存在的情况,字符串中存在且仅存在分开的 4 个自然数 
int main(){
	freopen("ip.in", "r", stdin);
	freopen("ip.out", "w", stdout);
	
	scanf("%s", s + 1);
	
	len = strlen(s + 1);
	for(register int i = 1; i <= len; i++){
		char ch = s[i];
		
		if(Number(ch)){
			num = (num << 1) + (num << 3) + (ch ^ 48); //如果当前字符是数字的话,累加起来 
			if(ch == '0'){ //判断一下前导零的情况  
				if(i == len) //如果他是最后一个字符,那他肯定不是前导零 
					continue;
				/*else if(i == 1){ //如果他是第一个字符,并且是零,那肯定是前导零  
					Istrue = false; //非法
					continue; 
				}*///错,不一定  
				else if(i == 1){
					if(Number(s[i + 1])){
						Istrue = false;
						continue; 
					} //如果他是第一个字符,并且是零,并且后边有数字,那肯定是前导零   
					else
						continue;
				} 
				else{ //是中间的一个字符  
					if(!Number(s[i - 1]) && Number(s[i + 1])){ //前边不是数字,后边是数字,说明他是自然数的第一位,那这就是前导零   
						Istrue = false;
						continue; 
					} 
					else
						continue; 
				}
			} 
		}
			
		else if(ch == '.'){ //如果当前字符是分割符  
			cnt_pos++; 
			if(!num){//分类讨论,如果前面读到的数字是 0 或者压根没有读到 
				//有可能压根就没读到, 比如 114.514.%%%%%%%...25.810 
				if(i == 1){
					//如果第一个字符就是分割符,没啥用直接跳过 
					Istrue = false; //这样就非法了  
					continue;
				}
				else{
					if(!Number(s[i - 1])) //如果他前边的字符不是数字,那肯定是压根没读到,没啥用,跳过
						continue;
					else //如果前边是数字,那这个数字只可能是 0 
						nums[++cnt_num] = num; 
				} 
			} 
			else{
				nums[++cnt_num] = num;
				num = 0;
			}
		} 
		
		else{ //当前字符是非法字符,类似分隔符 
			Istrue = false; //非法字符肯定非法  
			if(!num){ //他隔开的自然数是零还是没有读到 
			 	if(i == 1) //如果第一个字符就是非法字符,没啥用直接跳过 
				 	continue; 
				else{
					if(!Number(s[i - 1])) //如果他前边的字符不是数字,肯定是没有读到 
						continue;
					else
						nums[++cnt_num] = num;
				} 
			} 
			else{
				nums[++cnt_num] = num;
				num = 0;
			}
		}
	}
	nums[++cnt_num] = num;
	
	if(cnt_pos > 3) //有超过三个分割符,那他肯定非法 
		Istrue = false;
	for(register int i = 1; i <= 4; i++){
		if(nums[i] > 255){ //超过 255 非法 
			nums[i] = 255;
			Istrue = false; 
		}
	} 
			
	if(Istrue)
		puts("YES");
	else{
		puts("NO");
		for(register int i = 1; i <= 4; i++){
			if(i == 4)
				printf("%lld", nums[i]);
			else
				printf("%lld.", nums[i]);
		}
	} 
	
	return 0;
}

T2

正解是贪心,不过双向链表可过,复杂度应该都是 \(O(n)\) 的。

如果想要删除 \(A\),那么必须是以 \(AP\) 的形式。
不难发现尽可能删除 \(AP\) 一定会使答案更优(因为 \(A\) 会把一连串的 \(P\) 隔开)。
基于“ \(A\) 优先删除”的思想,本题就变成了一道栈的模拟题:
不断将 \(A\) 入栈,如果遇到 \(P\) 就将 \(A\) 出栈(即匹配到了一对 \(AP\)),最后一定会变成 \(P...PA....A\) 的形式,最后尽可能删除 \(P\) 即可。

赛时打了个双向链表,结果挂了 \(45\) 分。(纯属码力太弱)

Code

#include<stack> 
#include<cstdio>
#include<cstring>

using namespace std;

const int MAX = 10010;
int len, ans;
char s[MAX];
stack<int> s1, s2;

int main(){
	freopen("apstr.in", "r", stdin);
	freopen("apstr.out", "w", stdout);
	
	scanf("%s", s + 1);
	
	len = strlen(s + 1);
	for(register int i = 1; i <= len; i++){
		if(s[i] == 'A') s1.push(i);
		else if(s[i] == 'P'){
			if(!s1.empty()) s1.pop();
			else if(!s2.empty()) s2.pop();
			else s2.push(i);
		}
	}
	ans = s1.size() + s2.size();
	
	printf("%d", ans);
	
	return 0;
} 

T3

好题,考场上基本上想不到,这里我直接粘题解了。

因为老殷的毒瘤数据,最后一个点怎么卡也卡不过去,不得不用数据点分治这种奇技淫巧。

Code

//这道题简直就是教你怎么熟练使用 STL
#include<cstdio>
#include<string>
#include<bitset>
#include<iostream>
#include<algorithm>
#include<unordered_map>

using namespace std;

const int MAX = 1010;
int n;
int fa[MAX]; //记录父亲
string pru[MAX]; //需要继承的类
unordered_map<string, int> m;
bitset<MAX> anc[MAX]; //存每个类的父亲,加起来就是祖先了
string shujudainfenzhi = "ecw"; //摆烂了,卡不过去了 
bool tepan;

int main(){
	freopen("class.in", "r", stdin);
	freopen("class.out", "w", stdout);
	
	scanf("%d", &n);

	for(register int i = 1; i <= n; i++){
		int tot = 0; //继承的类(跌)的个数
		bool Istrue = true;
		string name,/*当前类的名字*/ tool/*没啥用,工具人一个,帮忙读掉 :*/;

		cin >> name >> tool;
		if(name == shujudainfenzhi && i == 1)
			tepan = true;
		
		while(cin >> pru[++tot]){
			if(pru[tot][0] == ';'){
				tot--;
				break;
			}
			if(m.find(pru[tot]) == m.end()){
				Istrue = false; //如果他继承的类没有定义,非法
				continue;
			}
		}

		if(tepan){
			puts("ok");
			continue;
		}
			
		if(m.find(name) != m.end()){ //如果已经定义过了,又定义一遍,非法
			puts("greska");
			continue;
		}

		for(register int j = 1; j <= tot && Istrue; j++)
			fa[j] = m.find(pru[j]) -> second;

		if(!Istrue){
			puts("greska");
			continue;
		}

		for(register int j = 1; j <= tot; j++){
			for(register int k = 1; k <= tot; k++){
				bitset<MAX> s = anc[fa[j]] & anc[fa[k]]; // j, k, 有无血缘关系(有无公共祖先)

				if(s.count() != 0/*有共同的祖先*/ && anc[fa[j]][fa[k]] == 0 && anc[fa[k]][fa[j]] == 0/*无继承关系*/){
					Istrue = false;
					break;
				}
			}
		}

		if(!Istrue){
			puts("greska");
			continue;
		}
		else puts("ok");

		for(register int j = 1; j <= tot; j++) //维护祖宗信息
			anc[i] = anc[i] | anc[fa[j]];
		anc[i].set(i, 1);
        m.insert(make_pair(name, i));
	}

	return 0;
}

T4

这更是道神仙题,到现在我就记住了老殷那个神奇的桶,
剩余的思路就看题解吧。

到最后,还是写()了 smtwy 大佬的解法,在 \(O2\) 的加持下,能勉强跑过老殷 \(1e9\) 的毒瘤数据。

Code

#include<cstdio>
#include<vector>
#include<algorithm>

using namespace std;

const int MAX = 1e6 + 10;
int n, m, cnt, l, r, sum, now;
long long M, N, B;
int head[MAX], deg[MAX];
int fa[MAX], q[MAX];
vector<int> num[MAX];
long long ans1, ans2 = -4611686018427387904;

struct Edge{
	int to, next;
}e[MAX << 2];

struct Picture{
	int belong; //属于哪个子图 
	int ns; //顶点数 
	int ms; //边数 
	int bs; //边界边数  
}p[MAX];

inline long long read(){
	long long x = 0, f = 1;
	char c = getchar();
	
	while(c < '0' || c > '9'){
		if(c == '-') f = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9'){
		x = (x << 1) + (x << 3) + (c ^ 48);
		c = getchar();
	}
	
	return x * f;
}

inline void Add(int u, int v){
	e[++cnt].to = v;
	e[cnt].next = head[u];
	head[u] = cnt;
}

void Clean(int n){
	for(register int i = 1; i <= n; i++){
		fa[i] = i;
		p[i].ns = 1;
		p[i].bs = deg[i]; 
	}
}

int Find(int x){
	return x == fa[x] ? x : fa[x] = Find(fa[x]);
}

void Merge(int x, int y){
	x = Find(x), y = Find(y);
	if(x != y){
		fa[y] = x;
		p[x].ns += p[y].ns;
		p[x].ms += p[y].ms + 1;
		p[x].bs += p[y].bs - 2;
	}
	else{
		p[x].ms += 1;
		p[x].bs -= 2;
	}
}

int main(){
	freopen("kdgraph.in", "r", stdin);
	freopen("kdgraph.out", "w", stdout);
	
	n = read(), m = read();
	M = read(), N = read(), B = read();
	for(register int i = 1; i <= m; i++){
		int u, v;
		u = read(), v = read();
		Add(u, v);
		Add(v, u);
		deg[u]++, deg[v]++; 
	}
	
	Clean(n);
	l = 1, r = 0;
	for(register int i = 0; i < n; i++){
		for(register int j = 1; j <= n; j++){
			if(deg[j] == i){
				if(i == 0)
					sum++;
				else
					q[++r] = j;
			}
		}
		
		if(!i) continue;
		
		while(l <= r){
			int t = q[l];
			l++;
			num[i].push_back(t);
			p[t].belong = i;
			sum++;
			
			for(register int k = head[t]; k; k = e[k].next){
				int v = e[k].to;
				deg[v]--;
				if(deg[v] == i) q[++r] = v;
			}
		}
		
		l = 1, r = 0;
		if(sum == n){
			now = i;
			break;
		}
	}
	
	for(register int i = now; i > 0; i--){
		int len = num[i].size();
		for(register int j = 0; j < len; j++){
			int t = num[i][j];
			for(register int k = head[t]; k; k = e[k].next){
				int v = e[k].to;
				if(i < p[v].belong)
					Merge(t, v);
				else if(i == p[v].belong && t < v)
					Merge(t, v);
			}
		}
		
		for(register int j = 0; j < len; j++){
			int t = num[i][j];
			int f = Find(t);
			
			long long tmp = M * p[f].ms - N * p[f].ns + B * p[f].bs;
			if(ans2 < tmp){
				ans1 = i;
				ans2 = tmp;
			}
		}
	}
	
	printf("%lld %lld", ans1, ans2);
	
	return 0;
} 

总结

这场难度应该算中等偏上吧,毕竟是 \(CSP - S\) 模拟赛,毕竟明天才是地狱试炼场级别的难度(事后诸葛亮了属于是)。

标签:Istrue,int,高考,register,long,2022,MAX,include,集训
来源: https://www.cnblogs.com/TSTYFST/p/16596431.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有