2026 · CSP-S · 二十连测 · 模拟四 题解
T1
不难发现,当只要有任意一组。之间的数字个数大于等于9那么答案一定为9
对于小于等于的情况。直接枚举即可。
代码
点击查看代码
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=2e5+5;
void solve()
{
int l1,r1,l2,r2,ans=0;cin>>l1>>r1>>l2>>r2;
if(r1-l1+1>=10||r2-l2+1>=10)
{
cout<<9<<endl;
return;
}
for(int i=l1;i<=r1;i++)
for(int j=l2;j<=r2;j++)
{
int x=i+j;
while(x) ans=max(ans,x%10),x/=10;
}
cout<<ans<<endl;
}
signed main()
{
freopen("digit.in","r",stdin);
freopen("digit.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int t;cin>>t;
while(t--) solve();
return 0;
}
T2
由于只能翻转,所以一个点最多关两个位置
把两个位置都是0的,一个位置是0,一个位置是1的,还有全部都是1的情况,单独筛选出来进行枚举就行。
代码
点击查看代码
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=1e6+5;
int n,m,mod=1e9+7;
int vis[maxn],cnt;
vector<int> v[maxn];
vector<pair<int,int> > g[maxn];
string s;
void dfs(int x)
{
for(auto to:g[x])
{
if(!vis[to.first]) vis[to.first]=vis[x]^to.second,dfs(to.first);
else if((vis[to.first]^vis[x])!=to.second)
{
cnt=-1;
return;
}
}
}
void solve()
{
cin>>n>>m;
for(int i=1;i<=m;i++) v[i].clear();
for(int i=1;i<=n;i++)
{
vis[i]=0;g[i].clear();
cin>>s;
s=' '+s;
for(int j=1;j<=m;j++) if(s[j]=='1') v[j].push_back(i);
}
for(int i=1;i<=(m+1)/2;i++)
{
if(v[i].size()+v[m-i+1].size()>2)
{
cout<<0<<endl;
return;
}
int s1=-1,s2=-1;
for(int x:v[i])
if(s1==-1)s1=x;
else s2=x;
for(int x:v[m-i+1])
if(s1==-1) s1=x;
else s2=x;
if(s2>0)
{
if(v[i].size()==v[m-i+1].size())
{
g[s1].push_back({s2,0});
g[s2].push_back({s1,0});
}
else
{
g[s1].push_back({s2,1});
g[s2].push_back({s1,1});
}
}
}
cnt=0;
for(int i=1;i<=n&&cnt!=-1;i++)
if(!vis[i])
{
cnt++;
int u=i;
vis[i]=2;
dfs(i);
}
if(cnt==-1)
{
cout<<0<<endl;
return;
}
int ans=1;
while(cnt--) ans=ans*2%mod;
cout<<ans<<endl;
}
signed main()
{
freopen("reverse.in","r",stdin);
freopen("reverse.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int t;cin>>t;
while(t--) solve();
return 0;
}
T3
遇到这种只差1的有两种做法。要么就是差分,要么就是减掉它对应的序号。
显然,这道题减掉序号会更好做。
这样题目就会转换成最大的连续段。
用双指针和对顶堆即可。
代码
点击查看代码
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=2e5+5;
int a[maxn];
signed main()
{
freopen("subarray.in","r",stdin);
freopen("subarray.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;
multiset<int> q2;
multiset<int,greater<int> > q1;
for(int i=1;i<=n;i++) cin>>a[i],a[i]-=i;
int sum1=0,sum2=0,ans=0;
for(int l=1,r=1;r<=n;r++)
{
q1.insert(a[r]);
sum1+=a[r];
while(q1.size()>q2.size()) q2.insert(*q1.begin()),sum1-=*q1.begin(),sum2+=*q1.begin(),
q1.erase(q1.begin());
while(q1.size()<q2.size()) q1.insert(*q2.begin()),sum2-=*q2.begin(),sum1+=*q2.begin(),
q2.erase(q2.begin());
int cnt=sum2-q2.size()*(*q1.begin())+q1.size()*(*q1.begin())-sum1;
while(cnt>k&&l<r)
{
if(q1.find(a[l])!=q1.end()) q1.erase(q1.find(a[l])),sum1-=a[l];
else q2.erase(q2.find(a[l])),sum2-=a[l];
while(q1.size()>q2.size()) q2.insert(*q1.begin()),sum1-=*q1.begin(),sum2+=*q1.begin(),
q1.erase(q1.begin());
while(q1.size()<q2.size()) q1.insert(*q2.begin()),sum2-=*q2.begin(),sum1+=*q2.begin(),
q2.erase(q2.begin());
cnt=sum2-q2.size()*(*q1.begin())+q1.size()*(*q1.begin())-sum1;
l++;
}
ans=max(ans,r-l+1);
}
cout<<ans<<endl;
}
return 0;
}
T4
会发现,这道题是一道树形背包
而背包本身的时间复杂度。可能会超。
于是,我们会发现。背包原来的时间复杂度,它在k小于等于n的算数平方根时。背包本身是完全可以跑的。而它大于时显然,这个时候,他的联通块个数就小于了
所以在k大于n的算数平方根时,我们的背包的容量换为联通块个数。
最后照常做背包即可。
代码
点击查看代码
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=2e5+5,mod=998244353;
map<int,int> dp[maxn];
int n,k;
vector<int> g[maxn];
void merge(int u,int v)
{
map<int,int> mp;
int num=0;
if (dp[v].count(k)) num+=dp[v][k],num%=mod;
if (dp[v].count(k+1)) num+=dp[v][k+1],num%=mod;
for(auto i:dp[u])
{
int x=i.first,y=i.second;
if(num) mp[x]+=y*num%mod,mp[x]%=mod;
for(auto j:dp[v])
{
int x2=j.first,y2=j.second;
if (x+x2>k+1) break;
mp[x+x2]+=y*y2%mod,mp[x+x2]%=mod;
}
}
dp[u].swap(mp);
dp[v].clear();
}
void dfs(int x,int fa)
{
dp[x][1]=1;
for(auto to:g[x])
{
if(to==fa) continue;
dfs(to,x);
merge(x,to);
}
}
signed main()
{
freopen("partition.in","r",stdin);
freopen("partition.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int t;cin>>t;
while(t--)
{
cin>>n>>k;
for(int i=1;i<=n;i++)
{
g[i].clear();
dp[i].clear();
}
for(int i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1,0);
int ans=0;
if(dp[1].count(k))
{
ans+=dp[1][k];
ans%=mod;
}
if(dp[1].count(k+1)) ans+=dp[1][k+1],ans%=mod;
cout<<ans<<endl;
}
return 0;
}
本文来自博客园,作者:Engle_Chen,欢迎转载,转载请注明原文链接:https://www.cnblogs.com/EagleChenzhilong/p/22896739
,感谢阅读!
浙公网安备 33010602011771号