2025 --【J+S 二十连测】-- 第十一套 总结

总结

T1

考场上很快写出了正解,但是由于题目理解错误,失分

T2

考场上很快写出了正解,没有问题,但是代码被吃了。。。

T3

考场上很快写出了正解,没有问题

T4

考场上很快写出了正解,但是假了,失分

T5

考场上很快写出了正解,但是假了,失分

题解

T1

照题意模拟即可,但是要倒着做

代码

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=2e5+5;
signed main()
{
	freopen("sky.in","r",stdin);
	freopen("sky.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int n;cin>>n;
	string s,t;cin>>s>>t;
	s=' '+s,t=' '+t;
	for(int i=n;i>=3;i--) if(s[i-1]==s[i-2]&&s[i-2]=='0') s[i]='0';
	cout<<(s==t?"YES":"NO");
	return 0;
}

T2

先重新标号,然后对 \(b\) 数组看是不是通过反转若干无交的子段即可

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=2e5+5;
signed main()
{
	freopen("sky.in","r",stdin);
	freopen("sky.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int n;cin>>n;
	string s,t;cin>>s>>t;
	s=' '+s,t=' '+t;
	for(int i=n;i>=3;i--) if(s[i-1]==s[i-2]&&s[i-2]=='0') s[i]='0';
	cout<<(s==t?"YES":"NO");
	return 0;
}

T3

用线段树模拟即可

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=2e6+5;
int a[maxn];
struct SGT
{
	int win[maxn<<2],jin[maxn<<2],n;
	void init(int len)
	{
		n=len;
	}
	void update(int x,int l,int r,int lt,int rt,int p)
	{
		if(l>rt||r<lt) return;
		if(l>=lt&&r<=rt&&l==r) win[x]+=p;
		if(l>=lt&&r<=rt) return;
		int mid=(l+r)>>1;
		update(x*2,l,mid,lt,rt,p);
		update(x*2+1,mid+1,r,lt,rt,p);
		int a=win[x*2],b=win[x*2+1];
		jin[x]=jin[x*2]+jin[x*2+1];
		if(a>=b||l>1) win[x]=abs(a-b);
		else win[x]=0,jin[x]+=b-a;
	}
}tree;
int read(){
	int x=0,f=1;
	char ch=getchar();
	while(!isdigit(ch)){
		ch=getchar();
		if(ch=='-') f=-1;
	}
	while(isdigit(ch)){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*f;
}
signed main()
{
	freopen("rain.in","r",stdin);
	freopen("rain.out","w",stdout);
	int n=(1<<(read())),m=read();
	for(int i=1;i<=n;i++) a[i]=read();
	tree.init(n);
	for(int i=1;i<=n;i++) tree.update(1,1,n,i,i,a[i]);
	while(m--)
	{
		int l=read(),r=read(),x=read();
		tree.update(1,1,n,l,r,x);
		cout<<tree.jin[1]<<endl;
	}
	return 0;
}

T4

我们先来把这道题弱化一下。把它弱化成只有高级廊桥。即加工零件这道题目。

由于这道题目里面有低级廊桥,所以我们考虑当前我到这一个点有三种情况。

  1. 我走了奇数个时间。
  2. 我走了偶数的时间,但是我走了高级廊桥。
  3. 我走了偶数个时间,但我没走高级廊桥。

对于前两种情况我们会发现他一定走了高级廊桥。那么我在高级廊桥上面来回移动。就可以增加二的时间。所以对于前两种情况,就是我到了那个点的最短时间,然后一直加2直到r。

而对于第三种情况的话。就只能在低级廊桥上面来回移动,那么就只能加4了。

但是第2种和第3种可能会有重复。当我们发现第3种情况到的时间比第2种早的时候,此时在第2种中和最短路径模式同余的那些情况,一定都是重复的。

反过来的话,我们就看,如果说第3种和第2种的最短路模4同余。那么第3种的每一种情况都是多余的。反之,我们将第2种情况的起点加二。因为两者均是偶数,余数差一定是二。然后接下来所有第3种情况一定都是多余的。

最后输出答案即可。

代码

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=2e5+5;
int dis1[maxn][2][2],vis[maxn][2][2];
int odd[maxn],evn0[maxn],evn1[maxn];
vector<pair<int,int> > g[maxn];
struct node
{
	int z,a,b,c;
	bool operator <(const node &a) const
	{
		return z>a.z;
	}
};
void bfs1()
{
	memset(dis1,0x3f,sizeof(dis1));
	dis1[1][0][0]=0;
	priority_queue<node> q;
	q.push({0,1,0,0});
	while(!q.empty())
	{
		int a=q.top().a,b=q.top().b,c=q.top().c;
		q.pop();
		if(vis[a][b][c]) continue;
		vis[a][b][c]=1;
		for(auto nxt:g[a])
		{
			int to=nxt.first,w=nxt.second,y=(b+w)%2,z=c|(w==1);
			if(dis1[to][y][z]>dis1[a][b][c]+w)
			{
				dis1[to][y][z]=dis1[a][b][c]+w;
				q.push({dis1[to][y][z],to,y,z});
			}
		}
	}
}
int f(int s,int p,int l,int r)
{
	if(s>r) return 0;
	int minn=(max(0ll,l-s)+p-1)/p,maxx=(r-s)/p;
	return max(0ll,maxx-minn+1);
}
signed main()
{
	freopen("friendship.in","r",stdin);
	freopen("friendship.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int n,m;cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int u,v,w;cin>>u>>v>>w;
		w++;
		g[u].push_back({v,w});
		g[v].push_back({u,w});
	}
	bfs1();
	memset(odd,0x3f,sizeof(odd));
	memset(evn0,0x3f,sizeof(evn0));
	memset(evn1,0x3f,sizeof(evn1));
	for(int i=1;i<=n;i++)
	{
		odd[i]=min(dis1[i][1][0],dis1[i][1][1]);
		evn1[i]=dis1[i][0][0];
		evn0[i]=dis1[i][0][1];
	}
	int q;cin>>q;
	while(q--)
	{
		int x,l,r,ans=0;cin>>x>>l>>r;
		if(odd[x]<inf) ans+=f(odd[x],2,l,r);
		if(evn1[x]<inf) ans+=f(evn1[x],4,l,r);
		if(evn0[x]<inf) ans+=f(evn0[x],2,l,r);
		if(evn0[x]<inf&&evn1[x]<inf)
		{
			if(evn0[x]<=evn1[x]) ans-=f(evn1[x],4,l,r);
			else
			{
				if(evn0[x]%4==evn1[x]%4) ans-=f(evn0[x],4,l,r);
				else ans-=f(evn0[x]+2,4,l,r);
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

T5

不难发现,如果说我每一次都取当前这个数的\(lowbit\)。那么先手必赢。所以我们只需要看\(n\)\(low bit\)是否大于 \(k\) 即可。

代码

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=2e5+5;
signed main()
{
	freopen("done.in","r",stdin);
	freopen("done.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int t;cin>>t;
	while(t--)
	{
		int n,k;cin>>n>>k;
		if((n&-n)<=k) cout<<"Alice"<<endl;
		else cout<<"Bob"<<endl;
	}
	return 0;
}
posted @ 2025-10-03 10:34  Engle_Chen  阅读(17)  评论(0)    收藏  举报