2023 CSP 游记

前言

此乃小 Oler 的一篇比赛游记,从今日后,还会进行详细的修订

注明:由于特殊原因,不能在考完试当天写下游记,深感遗憾。

Update 20231120:出分数线了,才发现自己一波擦线双一流带走了...

考试前夜

“最后一晚了,背背模板”

背完若干模板...(考场上一个都没用到)

“早睡养精神,不行,必须熬夜,看看 NBA 勇士的新闻日先...”

10:00 关灯睡觉了好吧。


考试当天

早上 morning

正常起床,精神不错,浅浅发个动态“++RP”。

早餐,一碗面和八个饺子,嘴里喝着瓶奶就前往 smzx 考点,感觉风挺大的。

到了考点,只见 dalao myz 早已等候多时,便谁便聊起今年题目大概难度。

接着,各路 dalao 陆续到达,such as ljs , xzk , zsw , hk , lsy , yyh ...

和dalao们互相寒暄几句就进入试室。


普及组

8:27 解压文件夹,直接看题。

8:30 考试正式开始,当时做题顺序为 T1T2T4T3

T1 apple

做题时间段:8:309:00

所用时:约 30 min

签到题必须拿下的好吧,第一眼按照做题思路,大概规律题,20 min 没找出规律,看一眼时间,想先打个暴力再看,打完后发现可以直接过,复杂度竟然为 O(log3n),大样例也水过了,赶紧润。

考试期望值:+100pts

实际值:+100pts

T2 road

做题时间段:9:009:40

所用时:约 40 min

看了题目像DP或贪心,再看数据范围 1e5,暂时想不到怎么定义状态,就先放下DP,去想贪心。

我的贪心很简单想,边走边取最小值,然后计算其贡献,最后相加就行了,10 min 打完。

这时候有趣的事情出现了,我按照题目顺序取大数据根本没注意题目的名字,取到了 bus 的大数据,绞尽脑汁调了 30 min 才发现拿错了,怪不得找不出错...拿回原来的大数据,轻松就过了,时间复杂度为 O(n2),为时不多了,赶紧润润润。

期望值:+100pts

实际值:+100pts

T3 uqe

做题时间段:10:3011:57

所用时:约 90 min

大模拟题,于是放到最后做,这时还剩 1h30min,安心做题,慢慢地按照题目打,打完还剩 10 min,测试样例,结果错了几个,当我发现问题时,已经是 11:54 了,由于是 11:57 停止答题,只剩 3 min,心里慌得一批,改了一半,只能把半成品交了上去。

期望值:+50pts

实际值:+10pts

T4 bus

做题时间段:9:4010:30

所用时:约 60 min

考前估最后一题会是DP题,结果出了道最短路,当时第一反应是找出性质,再用 dijkstra 跑个最短路,我也找出了一小点的性质,就是所走的路径长度必须为 k 的倍数,可惜当时没有想到可以用分层图,随便打了个bfs暴力就润去做 T3。

期望值:+10pts

实际值:0pts


出了考场,脑子一片空白,听说很多大佬都做出了 3 题,myz和xzk都做完了(意料之中)。

而我这个蒟蒻只做了两题,第 3 题生死未卜...(自卑了)


中午 noon

在 smzx 食堂随便吃了午饭,和众dalao讨论,这才发现考试时没时间忘了新建文本文档和启动 NOI Linux 了,祭!

心态崩溃,回到阶梯室休息,幸亏有以前比赛的经验,也没多想,安稳入睡。


下午 afternoon

1:40 被叫醒,一脸朦胧上楼,还不能进考场,还有些时间,醒醒神,顺便膜拜 dalao,沾沾欧气。

2:05 进考场,坐在座位上向众神祈祷,回应我的只有...


提高组

上午考砸了,这一年的努力就靠这最后一场了,背水一战...

2:30 提高考试开始。

复原当时做题顺序为 T1T2T3T4,比较佛系的顺序...

T1 lock

做题时间段:2:303:00

所用时:约 30 min

一开始认为第一题不会太过于简单,但又是第一题,也是要认真拿下的好吧,拿起草稿纸直接开始找性质,找半天发现数据范围 n8,而且密码锁只有五位,可以暴搜啊,一打还真可以,过来所有的样例,心里嘀咕着,咋还比普及 T1 还简单?(虽然我都因把题目想复杂而浪费时间了)

期望值:+100pts

实际值:+100pts

小插曲 I

T3题目样例解释有勘误,改正...(可惜我没怎么注意)

T2 game

做题时间段:3:003:20

所用时:约 20 min

一眼盯真,有点像zsq总喜欢出的蓝题消融——区间DP,一看数据又把我吓了一跳,n2×105,这区间DP最多蹭个 35 分,看看还有没有其他方法。

突然想起考试前几天刷题时才看到大佬总结区间的题目可以先设 fi 为开头或结尾定义状态,再浅浅结合题目,显然可以用 lasti 记录当前字符 i 其前面最后出现的位置,然后用栈维护,其实想到这时再坚持想想优化就可以对了,但当时脑子一傻,想不到怎么优化(失算了),只好打个 O(n2),水个 50 分算了,程序很简单,10 min 解决,然后就不管这题了,润润润。

期望值:+50pts

实际值:+50pts

T3 struct

做题时间段:3:204:55

所用时:约 100 min

对于我来说的毒瘤大模拟,由于时间充足,所以想尽可能拿高分,开始时是直奔正解的,结果做了 40 min,我又不会了,一看特殊性质ABCD,好像把我打的程序改改后,正好都可以拿下,于是就转换方向,去考虑特殊性质,改了 大约 45 min,官方没有给出特殊性质的数据,只好自己做数据,用了 10 min 就都过了,信心满满...可我忽视了一个很大的问题,就是考试时的题目有误,这边考场也是在开考后便立刻更改了勘误,而那时我在啃T1,后来也没多注意,也没怎么认真审题,按照样例解释打,最后导致爆 0,哭死...

期望值:+80pts

实际值:0pts

自我感觉如果按照原来样例解释,这题起码都有四五十分,痛哭o(╥﹏╥)o

小插曲 II

时间段:4:555:05

所用时:约 10 min

看着还剩一些时间到 5 点整,有了上午的经验,再加上中午请教 dalao,于是启动 NOI Linux,顺便写了个信息的文本文档,心里安稳些。

OK呀,NOI Linux上前三题程序都没有语法问题,那就赶紧去润T4。

T4 tree

做题时间段:5:056:20

所用时:约 80 min

这一年来学得最多的知识点就是图论了,这不就来了一道图论题(可惜我不会)...

一开始还对这题报点希望,后知后觉,这道题不是现在的我可以拿下的,那只能看看特殊性质,特殊性质的图很容易画出来,觉得可以推推式子贪心或者直接遍历一边图拿部分分,可我想得太简单了,这道题的特殊性质也不好推,结果白白浪费了 1h20min,最后只提交了一个暴力和两个特殊性质的错解(和普及组后两题的情况大差不差...)。

期望值:[0,10]pts

实际值:0pts

其实感觉是做最后一题状态不好,不然也不至于一点部分分都拿不了。

小插曲 III

这下总有时间留下来回去检查了,检查无误后,坐在座位上,心里默默估着自己的分数和今年大概分数线。

6:27 考试结束,停止答题。


一天的考试终于结束了,清闲走出考场,天已经很暗了,这感觉和去年一样...

myz和ljs两位真神用了近 3h A了第二题,拿下了两题,必须膜拜的好吧。


晚上 evening

出门吃了餐好的,逛了 3h 商场,买了双新鞋(高兴...)

回到家,学校信息群已经热开了锅,接着便去估分...


赛后总结

普及J

考试预期分数:100+100+50+10=260

实际分数:100+100+10+0=210

只有二等了(差5分!!!),废了废了...

Upd:擦线一等啊...

首先是做题时的心态有点小问题,有可能是早上还没开智,状态不佳。

第一题开始的思考方向错误了,然后就是第二题拿错了大数据点,耗费了时间,这本是不应该出现的失误。

第三题赛后改了半个小时也没把原程序改出来,后来经过 hk 的讲解才知道是自己考试时想得太复杂了,而且没有化简就直接硬做,最后的结果也是重构代码...(即使第二题没拖时间,按照原来的程序照样也改不出来,该反思一番)

第四题考场时输出个 1 也有 5 分,那样我就有一等了...(遗憾)

回归正题,第四题考场理论应该拿下的,考都考了,也是要分析一波原因的好吧,首先,dijkstra 是想到了,但是忘记了若遇到倍数的题,可以先往 上想(由于考前做过倍数的题所总结的,结果考试忘了...),简单来说就是分层图...啊啊啊!!!

提高S

考试预期分数:100+50+80+[0,10]=230

实际分数:100+50+0+0=150

惊险擦线水个一等...(终于可以摆脱绿勾了)

一橙三蓝,理论阿克

第一题橙题半个小时切出来了(受到小小猜测提高组的难度导致),还能接受,不用多说...

第二题,可多要说了,这题其实可以用匹配栈和哈希做的,然而暑假刚好上过这个专题(虽然说没讲匹配栈),还是深有感触,挺可惜...

而第二题想到了另外一种正解的,可以优化过掉的,能想到是因为考前做过同类型的题目,也是看谋篇大神的题解的总结,但是没想到优化,为了保险起见,就只拿了 50pts 的点,考后经过 zsw 的分析,才明白怎么优化...(听说 myz,ljs 两位大佬就是没优化过的做法,而且还A了)

敲重点!!第三题由于个人太过沉迷于打大模拟中,结果忘了看勘误!!!

结果可想而知,80pts0pts,就当一次教训吧,警示自己...不想多说这道题了(大模拟)...

第四题又是可惜,不知道是因为什么原因,考场上写的 less,本是大根堆,结果程序总是输出小根堆的结果,自认为是自己程序的问题...痛失 25pts0pts。(又又又听说 xzk 优先队列打对了,只拿了 5pts,促使他痛失一等,惋惜...而大佬 ljs 不知为啥,思路差不多,听说考场不小心写挂了,也一分未得)

大总结

总结来说就是考试时傻了又傻,绝对不能轻易原谅自己!!!

还有考试心态和做题的策略很重要,归根结底就是平常练习习惯没养成,还是得从习惯抓起...

最重要的一点就是硬实力不行,学了的不会用,还得用功啊...


番外

还原考试程序

此部分可跳过,后面有蒟蒻写的题解。

注明:取自考试压缩包,没有删改痕迹...

普及组 210pts

T1 apple 100pts

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,t,ans,res=-1;
signed main() {
	freopen("apple.in","r",stdin);
	freopen("apple.out","w",stdout); 
	scanf("%lld",&n);
	int x=n;
	while(t!=n) {
		int tem=(x-1)/3+1;
		if(x%3==1&&res==-1)
			res=ans+1;
		t+=tem,x-=tem,ans++;
	}
	printf("%lld %lld\n",ans,res);
	return 0;
} 

T2 road 100pts

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int n,d,v[N],a[N]; 
signed main() {
	freopen("road.in","r",stdin);
	freopen("road.out","w",stdout);
	scanf("%lld%lld",&n,&d);
	for(int i=1;i<n;i++)
		scanf("%lld",&v[i]);
	for(int i=1;i<=n;i++)
		scanf("%lld",&a[i]);
	int ans=0,minx=a[1],p=v[1],t=0;
	for(int i=2;i<n;i++) {
		if(a[i]<minx) {;
			ans+=minx*((p-t-1)/d+1);
			int tem2=t;
			t=((p-t-1)/d+1)*d+tem2-p;
			minx=a[i];
			p=0;
		}
		p+=v[i];
	}
	ans+=minx*((p-t-1)/d+1);
	printf("%lld\n",ans);
	return 0;
}

T3 uqe 10pts

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int t,m,a,b,c;
int pri[N];
map<int,int> mp;
signed main() {
	freopen("uqe.in","r",stdin);
	freopen("uqe.out","w",stdout);
	scanf("%lld%lld",&t,&m);
	for(int i=1;i<=m;i++)
		pri[i]=i*i,mp[i*i]=i;
	for(int i=1;i<=t;i++) {
		scanf("%lld%lld%lld",&a,&b,&c);
		int tem=b*b-4*a*c;
		if(tem<0) printf("NO\n");
		else {
			int x1=(-b+sqrt(tem));
			int x2=(-b-sqrt(tem));
//			cout<<x1<<" "<<x2<<"\n";
			if(x1>x2) {
				int t=sqrt(tem);
				if(t*t==tem) {
//					cout<<-b+t<<"\n";
					int p=-b+t,q=2*a;
					int pp=p,qq=q;
					if(p<0) p=-p;
					if(q<0) q=-q;
					int gc=__gcd(p,q);
					p/=gc,q/=gc;
					if(pp<0) p=-p;
					if(qq<0) q=-q;
					if(p==0) printf("0\n");
					else if(q==1) printf("%lld\n",p);
					else printf("%lld/%lld\n",p,q);
				} else {
					int p=-b,q=tem,x=0;
					int pp=p,qq=q;
					if(p<0) p=-p;
					if(q<0) q=-q;
					int gc=__gcd(p,a);
					p/=gc;
					gc=__gcd(q,a);
					q/=gc;
					if(pp<0) p=-p;
					if(qq<0) q=-q;
					for(int j=2;j<=sqrt(tem);j++)
						if(tem%(j*j)==0)
							x=j;
					if(p==0) {
						if(x==0) printf("sqrt(%lld)/2\n",q);
						else {
							if(x%2==0) printf("%lld*sqrt(%lld)\n",x/2,tem/x/x);
							else {
								if(x==1) printf("sqrt(%lld)/2\n",tem/x/x);
								else printf("%lld*sqrt(%lld)/2\n",x,tem/x/x);
							}
						}
					} else {
						if(p%2==0) {
							if(x==0) printf("%lld+sqrt(%lld)/2\n",p/2,q);
							else {
								if(x%2==0) printf("%lld+%lld*sqrt(%lld)\n",p/2,x/2,tem/x/x);
								else  {
									if(x==1) printf("%lld+sqrt(%lld)/2\n",p/2,tem/x/x);
									else printf("%lld+%lld*sqrt(%lld)/2\n",p/2,x,tem/x/x);
								}
							}
						} else {
							if(x==0) printf("%lld/2+sqrt(%lld)/2\n",p,q);
							else {
								if(x%2==0) printf("%lld+%lld*sqrt(%lld)/2\n",p,x/2,tem/x/x);
								else  {
									if(x==1) printf("%lld/2+sqrt(%lld)/2\n",p,tem/x/x);
									else printf("%lld/2+%lld*sqrt(%lld)/2\n",p,x,tem/x/x);
								}
							}
						}
					}
//					printf("%lld/2+sqrt(%lld)/2\n",p);
				}
			} else {
				int t=sqrt(tem);
				if(t*t==tem) {
					int p=-b-t,q=2*a;
					int pp=p,qq=q;
					if(p<0) p=-p;
					if(q<0) q=-q;
					int gc=__gcd(p,q);
					p/=gc,q/=gc;
					if(pp<0) p=-p;
					if(qq<0) q=-q;
					if(p==0) printf("0\n");
					else if(q==1) printf("%lld\n",p);
					else printf("%lld/%lld\n",p,q);
				} else {
				int p=-b,q=tem,x=0;
					int pp=p,qq=q;
					if(p<0) p=-p;
					if(q<0) q=-q;
					int gc=__gcd(p,a);
					p/=gc;
					gc=__gcd(q,a);
					q/=gc;
					if(pp<0) p=-p;
					if(qq<0) q=-q;
					for(int j=2;j<=sqrt(tem);j++)
						if(tem%(j*j)==0)
							x=j;
					if(p==0) {
						if(x==0) printf("sqrt(%lld)/2\n",q);
						else {
							if(x%2==0) printf("-%lld*sqrt(%lld)\n",x/2,tem/x/x);
							else {
								if(x==1) printf("-sqrt(%lld)/2\n",tem/x/x);
								else printf("-%lld*sqrt(%lld)/2\n",x,tem/x/x);
							}
						}
					} if(p%2==0) {
						if(x==0) printf("%lld-sqrt(%lld)/2\n",p/2,q);
						else {
							if(x%2==0) printf("%lld-%lld*sqrt(%lld)\n",p/2,x/2,tem/x/x);
							else {
								if(x==1) printf("%lld-sqrt(%lld)/2\n",p/2,tem/x/x);
								else printf("%lld-%lld*sqrt(%lld)/2\n",p/2,x,tem/x/x);
							}
						}
					} else {
						if(x==0) printf("%lld/2-sqrt(%lld)/2\n",p,q);
						else {
							if(x%2==0) printf("%lld-%lld*sqrt(%lld)/2\n",p,x/2,tem/x/x);
							else {
								if(x==1) printf("%lld/2-sqrt(%lld)/2\n",p,tem/x/x);
								else printf("%lld/2-%lld*sqrt(%lld)/2\n",p,x,tem/x/x);
							}
						}
					}
				}
			}
		}
	}
	return 0;
}
/*
9 1000
1 -1 0
-1 -1 -1
1 -2 1
1 5 4
4 4 1
1 0 -432
1 -3 1
2 -4 1
1 7 1
*/ 

T4 bus 0pts

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int oo=0x3f3f3f3f;
const int N=1e5+10;
int n,m,k,x,y,z;
struct Node {
	int to,nxt,st;
	Node() {
		to=nxt=st=0;
	}
	Node(int a,int b,int c) {
		to=a;
		nxt=b;
		st=c;
	}
} adj[N<<1];
int head[N],idx;
bool flag;
queue<int> a,b,c;
inline void add(int x,int y,int z) {
	adj[++idx]=Node(y,head[x],z);
	head[x]=idx;
}
void bfs(int s) {
	a.push(s);
	b.push(0);
	c.push(0);
	while(!a.empty()) {
		int px=a.front(); a.pop();
		int py=b.front(); b.pop();
		int pz=c.front(); c.pop();
//		cout<<px<<" "<<pz<<"\n";
		if(px==n) {
			if(pz%k==0) {
//				cout<<py<<"\n";
				printf("%lld\n",py+pz);
				flag=1;
				return ;
			}
		}
		for(int i=head[px];i;i=adj[i].nxt) {
			int v=adj[i].to,be=adj[i].st;
//			if(pz+1>=be) {
//				cout<<px<<" "<<v<<" "<<pz+1<<"\n";
//				if(be==3) cout<<be-pz+1<<"\n";
				a.push(v);
				b.push(max(py,be-pz+1));
				c.push(pz+1);
//			}
		}
	}
}
signed main() {
	freopen("bus.in","r",stdin);
	freopen("bus.out","w",stdout);
	scanf("%lld%lld%lld",&n,&m,&k);
	cout<<n<<" "<<m<<"\n";
	for(int i=1;i<=m;i++) {
		scanf("%lld%lld%lld",&x,&y,&z);
		add(x,y,z);
	}
	bfs(1);
	if(!flag) printf("-1\n");
	return 0;
} 
/*
5 5 3
1 2 0
2 5 1
1 3 0
3 4 3
4 5 1
*/ 

提高组 150pts

T1 lock 100pts

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,a[11],ans;
int s[11][6];
void dfs(int cnt) {
	if(cnt>5) {
		for(int i=1;i<=n;i++) {
			int p=0;
			for(int j=1;j<=5;j++) {
				if(s[i][j]!=a[j]) {
					if(p==1) {
						if(s[i][j-1]!=a[j-1]) {
							if((s[i][j-1]-a[j-1]+10)%10!=(s[i][j]-a[j]+10)%10)
								return ;
						} else return ;
					}
					p++;
					if(p>2) return ;
				}
			}
			if(p==0) return ;
		}
		ans++;
		return ;
	}
	for(int i=0;i<=9;i++) {
		a[cnt]=i;
		dfs(cnt+1);
	}
}
signed main() {
	freopen("lock.in","r",stdin);
	freopen("lock.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++) {
		s[i][0]=-1;
		for(int j=1;j<=5;j++)
			cin>>s[i][j];
	}
	dfs(1);
	printf("%lld\n",ans);
	return 0;
} 

T2 game 50pts

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int oo=0x3f3f3f3f;
const int N=1e5+10; 
int n,f[N],last[30];
int stk[N],top,ans;
string s;
signed main() {
	freopen("game.in","r",stdin);
	freopen("game.out","w",stdout);
	getline(cin,s);
	int len=s.size(); 
	for(int i=0;i<len;i++) {
		if(s[i]>='0'&&s[i]<='9')
			n=n*10+(s[i]-'0');
	}
	getline(cin,s);
	len=s.size();
	for(int i=0;i<=26;i++)
		last[i]=oo;
	for(int i=0;i<n;i++) {
		if(last[s[i]-'a']!=oo) {
			string w="";
			top=0;
			for(int j=last[s[i]-'a'];j<=n;j++) {
				w+=s[j];
				if(top&&s[j]==stk[top])
					top--;
				else stk[++top]=s[j];
				if(top==0&&w!="")
					ans++;
			}
		}
		last[s[i]-'a']=i;
	}
	printf("%lld\n",ans);
	return 0;
} 

T3 struct 0pts

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1001;
int n,op,k,pos=1;
int maxv[N];
string s,t,a;
map<string,int> mp;
//map<string,int> mp3;
map<string,int> mp2;
map<int,string> mp4;
vector<string> vec[N];
int Vnum;
signed main() {
	freopen("struct.in","r",stdin);
	freopen("struct.out","w",stdout);
	scanf("%lld",&n);
	for(int i=1;i<=n;i++) {
		cin>>op; 
		if(op==1) {
			cin>>s>>k;
			int maxx=0;
			++Vnum;
			vec[Vnum].push_back(s);
			for(int j=1;j<=k;j++) {
				cin>>t>>a;
				if(t=="byte") {
					maxx=max(1ll,maxx);
					vec[Vnum].push_back(a);
				} else {
					if(t=="short") {
						maxx=max(2ll,maxx);
						vec[Vnum].push_back(a);
					} else {
						if(t=="int") {
							maxx=max(4ll,maxx);
							vec[Vnum].push_back(a);
						} else {
							if(t=="long") {
								maxx=max(8ll,maxx);
								vec[Vnum].push_back(a);
							} else {
								maxx=max(maxv[mp[t]],maxx);
								vec[Vnum].push_back(a);
							}
						}
					}
				}
			}
			mp[s]=Vnum;
			maxv[Vnum]=maxx;
		}
		if(op==2) {
			cin>>t>>s;
			if(t=="byte") {
				mp2[s]=pos;
				mp4[pos]=s;
				pos++;
			} else {
				if(t=="short"){
					mp2[s]=pos;
					for(int j=pos;j<=pos+1;j++)
						mp4[j]=s;
					pos+=2;
				} else {
					if(t=="int") {
						mp2[s]=pos;
						for(int j=pos;j<=pos+3;j++)
							mp4[j]=s;
						pos+=4;
					} else {
						if(t=="long") {
							mp2[s]=pos;
							for(int j=pos;j<=pos+7;j++)
								mp4[j]=s;
							pos+=8;
						} else {
							int p=mp[t];
							int len=vec[p].size();
							int maxx=maxv[p];
							for(int j=1;j<len;j++) {
								mp2[s+'.'+vec[p][j]]=pos;
								for(int ll=pos;ll<=pos+maxx-1;ll++)
									mp4[ll]=s+'.'+ vec[p][j];
								pos+=maxx;
							}
						}
					}
				}
			}
		}
		if(op==3) {
			cin>>s;
			printf("%lld\n",mp2[s]-1);
		}
		if(op==4) {
			cin>>k;
			if(mp4[k+1]=="") printf("ERR\n");
			else cout<<mp4[k+1]<<"\n";
		}
	}
	return 0;
}

T4 tree 0pts

#include<bits/stdc++.h>
#define int long long
#define M(x,y) make_pair(x,y) 
using namespace std;
typedef pair<int,int> pll;
const int N=1e5+10;
int n,x,y,a[N],b[N],c[N];
struct Node {
	int to,nxt;
	Node() {
		to=nxt=0;
	}
	Node(int a,int b) {
		to=a;
		nxt=b;
	}
} adj[N];
struct Tree {
	int val,id;
} t[N];
int head[N],idx;
int dep[N],maxx[N];
int ans,w=0;
priority_queue<pll,vector<pll>,less<pll> > heap;
inline void add(int x,int y) {
	adj[++idx]=Node(y,head[x]);
	head[x]=idx;
}
void dfs(int u,int fa) {
	dep[u]=dep[fa]+1;
	for(int i=head[u];i;i=adj[i].nxt) {
		int v=adj[i].to;
		dfs(v,u);
	}
}
void dfs2(int u,int fa) {
	maxx[u]=t[u].val;
	for(int i=head[u];i;i=adj[i].nxt) {
		int v=adj[i].to;
		dfs2(v,u);
		maxx[u]=max(maxx[u],maxx[v]);
	}
}
void dfs3() {
	heap.push(M(t[1].val,1));
	while(!heap.empty()) {
		pll k=heap.top();
		heap.pop();
		int u=k.second;
		int distance=k.first;
		for(int i=head[u];i;i=adj[i].nxt) {
			int v=adj[i].to;
			w++;
			ans=max(ans,t[v].val-dep[u]+w-1);
//			cout<<w<<" "<<v<<" "<<t[v].val-dep[u]+w-1<<"\n";
			heap.push(M(t[v].val,v));
		}
	}
}
signed main() {
	freopen("tree.in","r",stdin);
	freopen("tree.out","w",stdout);
	scanf("%lld",&n);
	for(int i=1;i<=n;i++)
		scanf("%lld%lld%lld",&a[i],&b[i],&c[i]);
	int cnt=0;
	bool flag=1;
	for(int i=1;i<n;i++) {
		scanf("%lld%lld",&x,&y);
		if(y-x!=1) flag=0;
		if(x==1) cnt++;
		add(x,y);
	}
	if(flag) {
//		cout<<n<<"\n";
		int day=0,maxx=0;
		for(int i=1;i<=n;i++) {
			day++;
			if(c[i]>0) {
				int s=b[i]+c[i];
				int m=a[i];
				int g=c[i];
				int ret=0;
				if(g!=0) ret=(m-s-1)/g+1;
				else  ret=(m-s-1)+1;
				if(ret*g<a[i]) ret++;
				maxx=max(day+ret,maxx);
			} else {
				int ret=0,pp=0;
				for(int j=1;;j++) {
					ret+=max(1ll,b[i]+j*c[i]);
					if(ret>=a[i]) {
						pp=j;
						break;
					} 
				}
				maxx=max(day+pp,maxx);
			}
		}
		printf("%lld\n",maxx);
	} else {
		if(cnt==n-1) {
			for(int i=2;i<=n;i++) {
				if(c[i]>=0) {
					t[i].val=111;
					t[i].id=i; 
				} else ;
			}
		} else {
//			cout<<111111<<"\n";
			dfs(1,0);
			for(int i=1;i<=n;i++) {
				t[i].val=dep[i]+(a[i]-1)/b[i]+1;
				t[i].id=i; 
//				cout<<t[i].val<<" ";
			}
//			cout<<"\n";
			dfs2(1,0);
			dfs3();
			printf("%lld\n",ans);
		} 
	}
	return 0;
}
/*
4
5 1 0
8 2 0
3 1 0
11 2 0
1 2
1 3
3 4
*/

题解区

主要讲一下我没有水过的题目...

J-普及组

前两题已经水过了,不多说了,代码在上方...

T3

闲话:一道模拟题,虽说考场上没有做出来,但考后在 hk 的帮助下改出来了...

入正题,对于求解二元一次方程 ax2+bx+c=0,(a0),学过的都知道公式是这样的(题目也有说明):

Δ=b24ac

x1,2=b±Δ2a

可以对上面的式子进行化简,如下:

x1,2=b2a±Δ2a

为了方便讨论,这里把 a 取正,即 a=|a|

题目要求 x1,2 两个实数解中的最大值,那若加必定可以使得解最大,那么只需要求解

x=b2a+Δ2a

现在就把问题转换为如何求解上式了,这里我们需要分类讨论了,不做赘述,大体是按输出形式分为两种情况,或是形如 a,或是形如 a+b 的(此处的 a,b 都是实数)。

若是属于后一种情况,又需对实数中的有理数和无理数分别做处理即可,此处需要用到 gcd 等一类的操作。

这里重点说一下 Δ 怎么处理,首先判断 Δ 是否是个完全平方数,如果是,那就直接开平方,若不是,则需要使之成为最简二次根式,上了初二的都会。简单说说,把 Δ 化简后的答案分为有理数 y 和无理数 w,还有除数 x,输出 +y×sqrt(w)/x 即可。

详细见代码...

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int t,m,a,b,c,y,w;
signed main() {
//	freopen("uqe.in","r",stdin);
//	freopen("uqe.out","w",stdout);
	scanf("%lld%lld",&t,&m);
	for(int i=1;i<=t;i++) {
		scanf("%lld%lld%lld",&a,&b,&c);
		if(a<0) a=-a,b=-b,c=-c;
		int tem=b*b-4*a*c;
		int x=a*2,gc,cnt;
		bool flag=1;
		if(tem<0) 
			printf("NO\n");
		else {
			if(tem==0) {
				if(b==0) printf("0\n");
				else {
					b=-b;
					gc=__gcd(x,b);
					x/=gc,b/=gc;
					if(abs(x)==1) printf("%lld\n",x*b);
					else {
						if(x<0) x=-x,b=-b;
						printf("%lld/%lld\n",b,x);
					}
				}
			} else {
				int t=sqrt(tem);
				if(t*t==tem) {
					b=-b+t;
					gc=__gcd(x,b);
					x/=gc,b/=gc;
					if(abs(x)==1) printf("%lld\n",x*b);
					else {
						if(x<0) x=-x,b=-b;
						printf("%lld/%lld\n",b,x);
					}
				} else {
					if(b!=0) {
						flag=0;
						b=-b;
						gc=__gcd(x,b);
						x/=gc,b/=gc;
						if(abs(x)==1) printf("%lld",x*b);
						else {
							if(x<0) x=-x,b=-b;
							printf("%lld/%lld",b,x);
						}
					}
					t=sqrt(tem),cnt=0;
					y=w=1;
					for(int i=2;i<=t;i++) {
						while(tem%i==0) {
							cnt++;
							if(cnt==2)
								y*=i,cnt=0;
							tem/=i;
						}
						if(cnt==1) w*=i,cnt=0;
					}
					if(tem>1) w*=tem;
					x=a*2;
					gc=__gcd(y,x);
					y/=gc,x/=gc;
					y=abs(y),x=abs(x);
					if(!flag) printf("+");
					if(y!=1) printf("%lld*",y);
					printf("sqrt(%lld)",w);
					if(x!=1) printf("/%lld",x);
					printf("\n");
				}
			}
		}
	}
	return 0;
}

S-提高

T2

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e6+10;
int n,a[N][31],ans;
int last[N],f[N];
string s;
signed main() {
	scanf("%lld",&n);
	getchar();
	getline(cin,s);
	s=' '+s;
	for(int i=1;i<=n;i++) {
		last[i]=i;
		int tem=a[last[i-1]][s[i]-'a'];
		if(tem) {
			last[i]=last[tem-1];
			f[i]=f[tem-1]+1;
		}
		a[last[i]][s[i]-'a']=i;
		ans+=f[i];
	}
	printf("%lld\n",ans);
	return 0;
} 
posted @   Fireworks_Rise  阅读(89)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示