NOIP2023 游记及反思

游记

进场前的同学们

image

柠檬熟了、Nitaycke、Prms_Prmt、b1t

image

zhicheng,meatherm

开题,很快啊,

第一题不就桶排,今年签到没有去年恶心啊(9:00)

第二题,观察到每个变量最后只有一个值的依靠(或者干脆定值),建图染色就好了啊,冲冲冲,9:30 就过完了样例

此时:优势在我!

第三题,发现就是区间匹配啊,转化为一个四联通的网格图走路,思考特殊性质,不会,思考 bitset 能不能艹 \(4\times 10^4\),没成功,35 pts 跑路。11:20 了,感觉比较寄

第四题,看起来我会 \(O(n^2)\) dp!我还会特殊性质 AB,那我是不是达到预期了啊,然后开始冲暴力。

写完数组,突然想到我的目的是完成挑战,开始结束一定在端点上,写个 dp 式子,发现和某个联考题很像,是可持久化李超?哦 \(ij\) 没有交错啊,那是不是单调队列啊。这个开始的价值动态更新,那扫描线掉区间右端点,加区间左端点,用线段树维护就完了。此时11:40,高兴麻了,那 300+ 是不是到 SC NOIP 队线了,开冲。

12:10 就写完了,怎么过不去样例啊?哦 \(xy\) 反了。测样例 \(2\),过不去,哦多测挂了。

然后还是过不去?为什么啊???

是不是结论假了啊?没道理啊。

…………

然后就没有然后了。

期望得分 \(100+100+35+0=235\),应该没挂分。

出考场不久就发现把相邻判成离散化后相邻了,艹艹艹!喜挂 \(100pts\) 😅!我草怎么考场上被机械降智了啊!原来的 \(335pts\) 至少也是遥遥领先我们机房的,现在寄了吧。

完蛋!我被降智包围了!♿♿♿。自闭。♿♿♿。暴力有 \(56\) 分,,,

出来发现 Meatherm 挂的更严重,第二题开始就心态炸完了。Hanghang 第一题看错了但是是对的(好像还挂了什么分),Nityacke 说他第一题 FailPreTest 了(是 \(10pts\) ),zhicheng 第三题写挂了,绷。

但是今年是 easy round 啊,是不是高二人均阿克了,高一希望比较渺茫啊。

补:高二机房没有 \(3\) 个会 T3 的,遥遥领先!优势在我啊!

反思:

前两道题倒是比较顺利。

第三题可能不在我目前的能力范围内,在时间充裕的时间内思考一个小时然后暴力是正确的。

最大的失误在第四题。第四题很快想出了正解,很快写完了,却没有考虑到这样的罕见的小细节;检查时,我使用了一般的检查方法,也重新思考了逻辑,感觉非常对,然后就没有发现错误。

事实上,如果我预先写好暴力,不仅至少我可以得到最低的暴力分,我应该也可以结合暴力和不算太大的样例 \(2\) 分析出错误。所以非签到题先打暴力显然是明智的选择。

赛后我发现,我犯错误的原因是这样:我在纸上写的 \(O(n^2)\) dp 方程是这样:

\[f_i=-(i+1)d+\max(g_{j-1}+c_j+jd) \]

这里 \(c_j\) 是从 \(j\) 出发到 \(i\) 的贡献,使用扫描线,\(g\) 是这一个位置不跑步打卡的最大能量。

这是正确的。再结合“一定是从区间端点开始和结束”就可以获得离散化+线段树优化 dp 的正解。但是,这一把 \(O(n^2)\) dp 方程转化为 \(O(m^2)\)(未经线段树优化)的过程只在我脑中进行和代码用线段树实践了,未在纸上清晰地展示出来:这带来一些谬误,由离散化前后的值不同引起。

新的 dp 方程应该是这样:

\[\left\{\begin{matrix} f_i=-(rev_i+1)d+\max(g_{j}+c_j+rev_jd) & (rev_j>rev_{j-1}+1)\\ f_i=-(rev_i+1)d+\max(g_{j-1}+c_j+rev_jd) & (rev_j=rev_{j-1}+1)\\ \end{matrix}\right. \]

\(rev\) 指离散化数组代指的原值。这对线段树优化的影响不大。

显然这是容易处理的,我却在脑袋里和代码里忽略了第一种情况,导致答案一直在某几个点偏小,最终也没有发现这个问题。所以,另一个教训是一定要把思路和可能想到的细节清晰地展现在纸上

贴下代码吧

T1

#include<bits/stdc++.h>
using namespace std;
const int maxn=3e3+5;
int n,m,cnt[maxn][27];
char s[maxn];
pair<int,int> p1[maxn][maxn],p2[maxn][maxn];
bool operator ==(pair<int,int> a,pair<int,int> b){
	return a.first==b.first&&a.second==b.second;
}
signed main(){
//	system("fc dict4.ans my.out");
	freopen("dict.in","r",stdin);
	freopen("dict.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>s+1;
		for(int j=1;j<=m;j++)cnt[i][s[j]-'a'+1]++;
	}
	for(int i=1;i<=n;i++){
		int c=0;
		for(int k=1;k<=26;k++){
			if(cnt[i][k])p1[i][++c]={k,cnt[i][k]};
		}
		for(int k=c+1;k<=26;k++)p1[i][k]={0,0};
		c=0;
		for(int k=26;k>=1;k--){
			if(cnt[i][k])p2[i][++c]={k,cnt[i][k]};
		}
		for(int k=c+1;k<=26;k++)p2[i][k]={0,0};
	}
	for(int i=1;i<=n;i++){
		bool ck=1;
		for(int j=1;j<=n;j++){
			if(i==j)continue;
			bool can=0;
			for(int k=1;k<=26;k++){
				if(p1[i][k].second==0)break;
				if(p1[i][k]!=p2[j][k]){
					if(p1[i][k].first!=p2[j][k].first){
						can=(p1[i][k].first<p2[j][k].first);
						break;
					}else{
						can=0;
						break;
					}
				}
			}
			if(!can){
//				cout<<i<<" > "<<j<<endl;
				ck=0;break;
			}
		}
		cout<<ck;
	}
	return 0;
}
/*
4 7
abandon
bananaa
baannaa
notnotn
*/

T2

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
vector<pair<int,int> > e[maxn];
int val[maxn],C,Test,n,m,ans[maxn];
const int T=1e5+1,F=1e5+2,U=1e5+3;
int anti(int x){
	if(x==T)return F;
	if(x==F)return T;
	if(x==U)return U;
	return -x;
}
bool vis[maxn];
void add_edge(int u,int v,int w){
	e[u].push_back({v,w});
	e[v].push_back({u,w});
}
void dfs1(int u){
	for(auto E:e[u]){
		int v=E.first,w=E.second;
		if(w)ans[v]=anti(ans[u]);
		else ans[v]=ans[u];
		if(!vis[v]){
			vis[v]=1;
			dfs1(v);
		}
	}
}
bool cur=1;
int cnt=0;
void dfs2(int u){
	++cnt;
	for(auto E:e[u]){
		int v=E.first,w=E.second;
		if(!vis[v]){
			vis[v]=1;
			if(w)ans[v]=anti(ans[u]);
			else ans[v]=ans[u];
			dfs2(v);
		}else{
			if(w){
				if(ans[v]!=anti(ans[u]))cur=0;
			}else{
				if(ans[v]!=ans[u])cur=0;
			}
		}
	}
}
signed main(){
	freopen("tribool.in","r",stdin);
	freopen("tribool.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>C>>Test;
	while(Test--){
		cin>>n>>m;
		for(int i=1;i<=n;i++)val[i]=i;
		for(int i=1;i<=m;i++){
			char tp;int x,y;
			cin>>tp;
			if(tp=='T'){
				cin>>x;
				val[x]=T;
			}else if(tp=='F'){
				cin>>x;
				val[x]=F;
			}else if(tp=='U'){
				cin>>x;
				val[x]=U;
			}else if(tp=='+'){
				cin>>x>>y;
				val[x]=val[y];
			}else if(tp=='-'){
				cin>>x>>y;
				val[x]=anti(val[y]);
			}
		}
		for(int i=1;i<=n;i++)e[i].clear();
		memset(vis,0,sizeof(vis));
		memset(ans,0,sizeof(ans));
		for(int i=1;i<=n;i++){
			if(val[i]<=(1e5)){
				if(val[i]<0)add_edge(i,-val[i],1);
				else add_edge(i,val[i],0);
			}
		}
		for(int i=1;i<=n;i++){
			if(val[i]>(1e5)){
				ans[i]=val[i];
				if(!vis[i])vis[i]=1,dfs1(i);
			}
		}
		int Ans=0;
		for(int i=1;i<=n;i++){
			if(vis[i]==1&&ans[i]==U)++Ans;
		}
		for(int i=1;i<=n;i++){
			if(!vis[i]){
				cur=1;cnt=0;
				vis[i]=1;ans[i]=T;
				dfs2(i);
				if(cur==0)Ans+=cnt;
			}
		}
		cout<<Ans<<endl;
	}
	return 0;
}
/*
1 3
3 3
- 2 1
- 3 2
+ 1 3
3 3
- 2 1
- 3 2
- 1 3
2 2
T 2
U 2
*/

/*
Bless me
I wish that I can get more than 250 at NOIP
Then I may attend NOI2024 as NOID or even SC province team
rp++
British_union
*/

改过的 T4(就是那里错了/ll)

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=2e5+5;
int C,T,n,m,k,d;
int xds[maxn<<2],add[maxn<<2];
void ADD(int k,int v){
	add[k]+=v,xds[k]+=v;
}
#define ls (k<<1)
#define rs (k<<1|1)
#define mid ((l+r)>>1)
void pushdown(int k){
	ADD(ls,add[k]);
	ADD(rs,add[k]);
	add[k]=0;
}
void pushup(int k){
	xds[k]=max(xds[ls],xds[rs]);
}
int query(int k,int l,int r,int x,int y){
//	assert(xds[k]>=0);
	if(x<=l&&r<=y)return xds[k];
	pushdown(k);
	int res=0;
	if(x<=mid)res=max(res,query(ls,l,mid,x,y));
	if(mid<y)res=max(res,query(rs,mid+1,r,x,y));
	return res;
}
void modify(int k,int l,int r,int x,int y,int v){
//	assert(v>=0);
	if(x<=l&&r<=y)return ADD(k,v);
	pushdown(k);
	if(x<=mid)modify(ls,l,mid,x,y,v);
	if(mid<y)modify(rs,mid+1,r,x,y,v);
	pushup(k);
}
unordered_map<int,int> mp;
int l[maxn],r[maxn],v[maxn];
int qsy[maxn],rev[maxn],cnt=0,now=0;
vector<int> e[maxn];
int f[maxn],g[maxn];
signed main(){
//	freopen("run.in","r",stdin);
//	freopen("run.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>C>>T;
	for(int zfy=1;zfy<=T;zfy++){
		memset(xds,0,sizeof(xds));
		memset(add,0,sizeof(add));
		cin>>n>>m>>k>>d;
		cnt=0;
		for(int i=1;i<=m;i++){
			int x,y;cin>>x>>y;
			r[i]=x,l[i]=x-y+1;
			cin>>v[i];
			qsy[++cnt]=l[i],qsy[++cnt]=r[i];
		}
		sort(qsy+1,qsy+cnt+1);
		mp.clear();
		now=0;
		for(int i=1;i<=cnt;i++){
			if(!mp.count(qsy[i])){
				mp[qsy[i]]=++now;
				rev[now]=qsy[i];
			}
		}
//		for(int i=1;i<=now;i++)cout<<i<<" "<<rev[i]<<endl;
		for(int i=1;i<=m;i++)l[i]=mp[l[i]],r[i]=mp[r[i]];
		for(int i=1;i<=now;i++)e[i].clear();
		for(int i=1;i<=m;i++)e[r[i]].push_back(i);
		memset(f,0,sizeof(f));
		memset(g,0,sizeof(g));
		int L=1,ans=0;
		for(int i=1;i<=now;i++){
			g[i]=max(g[i-1],f[i-1]);
			modify(1,1,now,i,i,(rev[i]==rev[i-1]+1?g[i-1]:g[i])+rev[i]*d);
//			modify(1,1,now,i,i,g[i-1]+rev[i]*d);
			for(auto u:e[i]){
				modify(1,1,now,1,l[u],v[u]);
			}
			while(L<i&&rev[i]-rev[L]+1>k)++L;
			f[i]=-(rev[i]+1)*d+query(1,1,now,L,i);
		}
		cout<<max(g[now],f[now])<<endl;
	}
	return 0;
}
/*
1 1
3 2 2 1
2 2 4
3 2 3
*/

/*
I have nothing to say here.
*/

T3

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+5;
int x[maxn],y[maxn],xm[maxn],ym[maxn];
bool mp[2005][2005],vis[2005][2005];
bool solve(int a[],int b[],int n,int m){
	if(a[1]>b[1])return solve(b,a,m,n);
	for(int i=1;i<=m;i++){
		for(int j=1;j<=n;j++){
			mp[i][j]=(b[i]>a[j]);
		}
	}
	if(!mp[1][1])return 0;
	vis[1][1]=1;
	for(int i=1;i<=m;i++){
		for(int j=1;j<=n;j++){
            if(i==1&&j==1)continue;
			vis[i][j]=(mp[i][j]&(vis[i-1][j]|vis[i][j-1]));
		}
	}
	return vis[m][n];
}
bool solve2(int a[],int b[],int n,int m){
	if(a[1]>b[1])return solve(b,a,m,n);
	if(a[1]==b[1])return 0;
	int r=1;
	for(int i=1;i<=m;i++){
		if(a[r]>=b[i])return 0;
		while(r<=n&&a[r]<b[i])++r;
	}
	return 1;
}
int C,n,m,q;
signed main(){
	freopen("expand.in","r",stdin);
	freopen("expand.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>C>>n>>m>>q;
	for(int i=1;i<=n;i++)cin>>x[i];
	for(int i=1;i<=m;i++)cin>>y[i];
	if(C<=7){
		cout<<solve(x,y,n,m);
		while(q--){
			for(int i=1;i<=n;i++)xm[i]=x[i];
			for(int i=1;i<=m;i++)ym[i]=y[i];
			int kx,ky;cin>>kx>>ky;
			while(kx--){
				int p,v;cin>>p>>v;
				xm[p]=v;
			}
			while(ky--){
				int p,v;cin>>p>>v;
				ym[p]=v;
			}
			cout<<solve(xm,ym,n,m);
		}
	}else{//Greedy
		solve2(x,y,n,m);
		while(q--){
			for(int i=1;i<=n;i++)xm[i]=x[i];
			for(int i=1;i<=m;i++)ym[i]=y[i];
			int kx,ky;cin>>kx>>ky;
			while(kx--){
				int p,v;cin>>p>>v;
				xm[p]=v;
			}
			while(ky--){
				int p,v;cin>>p>>v;
				ym[p]=v;
			}
			solve2(xm,ym,n,m);
		}
	}
	return 0;
}
/*
3 3 3 3
8 6 9
1 7 4
1 0
3 0
0 2
1 8
3 5
1 1
2 8
1 7
*/

/*
I think this problem could be difiicult

But I can imagine that Meatherm,Nityacke(SC-114 henghengaa),Zhicheng and others can easily AC it

Such a pity that I have no ability to that :(

I love qsy

*/
posted @ 2023-11-18 20:33  British_Union  阅读(292)  评论(0编辑  收藏  举报