联合省选2025游记

image

赛前

正式比赛最摆烂的一集。

还是一样的赛前模板,写的题比 NOIP 的题少太多了。

image

对比 NOIP:

image

省选赛前饺子一中发了咖啡和士力架。


赛时

Day 1

先开 T1,感觉是个 妙妙性质题,感觉判断一个数是否可能为中位数可以通过一个远古 trick 来解决,也就是把小于这个数的数看成 \(-1\),等于这个数的可以看成 \(-1,0,1\) 的任意一种,而大于这个数的可以看成 \(1\)

但他能取得数是一段区间,于是就不会了。

然后又会了,感觉能等于这个数的话我们选 \(-1,0,1\) 感觉非常优秀,剩下的已经确定是 \(-1\) 还是 \(1\) 了。

于是我们就得到了 性质B 的做法:离散化后维护每个区间的左右端点,之后枚举每个可能的答案,然后把新加入的线段记录一个值叫 valt 表示有多少个任意取值的,把出去的加入 valf,最初都在 valz,之后判断是否合法即可。

但我要想正解,我们考虑加入 valt 的一定是数量最多的,然后我们把 valfvalz 改成一个区间的形式,记录他能取到的最小值和最大值,这样会构成两个区间,看看这两个区间经过 valt 的调整后是否能相交就做完了。

但我这个想法从 \(9:21\) 开写跳到 \(11:12\) 才过拍,细节巨多:

  • 离散化时要给右端点加 \(1\),这样才是一个实打实的区间。
  • 如果 valt=0 的话即使两区间相交了也不行。

写代码十分钟,调代码两小时

拿下 T1 大样例后拿着性质 AB 的代码拍了拍,拍了一万组,开了 T2:

感觉一眼不会,只能打暴力和性质了,先拿下了暴力的二十分,之后开了 T3,同样码了 \(O(n!)\) 的做法。

之后就去思考了无修改的性质,感觉可以按照 \(dfn\) 重新编号后再跑,但感觉码起来非常困难,还要维护 st表 之类的才能进行区间查询。

最后 \(Day 1=100+20+8=128\),遗憾离场。


upd:2025.3.11:

自测没挂分。


Day 2

来到我的位置是才发现昨天带的东西一点没吃,于是先进行了一个士力架的吃,之后开了 T1:

看到 T1,我会一个暴力跳的做法,之后注意到有一个性质是 \(a,b\) 单调递增,感觉可以二分,于是暴力跳,暴力修改,就得到了一个不知道能拿多少分的我的赛事代码:

//I do think Nothing is Required but bruteforce
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define Air
namespace io{
	int read(){
		int t=0,f=1;char ch=getchar();
		while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
		while(ch>='0'&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
		return t*f;		
	}
	void write(int x){
		if(x<0){putchar('-');x=-x;}
		if(x>=10)write(x/10);
		putchar(x%10+'0');
	}
} 
using namespace io;
int n;
const int N=3e5+10;
int TCS;
struct node{
	int st,ed,tim;
	int id;	
	friend bool operator<(node x,node y){
		return x.tim<y.tim;
	}
}box[N];

int a[N];
int move(int st,int ed,int id){
	if(st==ed)return 0;
	if(st<ed){//right
		int idd=upper_bound(a+1,a+1+n,ed)-a-1;
		if(idd==id){
			a[id]=ed;
			return ed-st;//direct move
		}
		int dis=idd-id;
		int step=move(a[idd],ed+dis,idd);
		for(int i=id;i<idd;i++){
			step+=(i-id)+ed-a[i];
			a[i]=(i-id)+ed;
		}
		return step;
	}
	else{
		int idd=lower_bound(a+1,a+1+n,ed)-a;
		if(idd==id){
			a[id]=ed;
			return st-ed;//direct move
		}
		int dis=id-idd;
		int step=move(a[idd],ed-dis,idd);
		for(int i=id;i>idd;i--){
			step+=a[i]-ed+(id-i);
			a[i]=ed-(id-i);
		}
		return step;
	}
}
void work(){
	n=read();
	for(int i=1;i<=n;i++){
		box[i]={read(),read(),read(),i};
		a[i]=box[i].st;
	}
	sort(box+1,box+1+n);
	if(TCS==5||TCS==9||TCS==13||TCS==19||TCS==20){//16pts
		int kk=0;
		for(int i=1;i<=n;i++){
			kk+=box[i].ed-box[i].st;
			if(kk>box[i].tim){
				puts("No");
				return ;
			}		
		}
		puts("Yes");
		return ;
	}
	int kk=0;
	for(int i=1;i<=n;i++){
		kk+=move(a[box[i].id],box[i].ed,box[i].id);
		if(kk>box[i].tim){
			puts("No");
			return ;
		}
	}
	puts("Yes");
	return ;
}
signed main(){
#ifdef Air
	freopen("move.in","r",stdin);
	freopen("move.out","w",stdout);
#endif
	TCS=read();
	int T=read();
	while(T--){
		work();
	}
	//tai kun nan le
	return 0;
}

之后我去考虑了优化,感觉像区间修改等差数列,但如何二分,我这里不会维护了,感觉不会处理连环的情况,之后就放弃了,打了 T2、T3 的暴力,发现 T2 暴力无法通过第二个小样例,边红边调,最终拼尽全力无法战胜。

估分:

\(Day2=[44,80]+0+8=?\)


upd:25.3.11

自测:
\(Day2=60+4+8=72\)

甚至反向挂分。


赛后

在洛谷上订了 D2T1 感觉非常妙,原来可以维护 \(ed_i-i\) 我太菜了。

posted @ 2025-03-11 20:46  Air2011  阅读(35)  评论(1)    收藏  举报