2026 · CSP-S · 二十连测 · 模拟八题解
T1
容易想到二分答案所以我们可以考虑2分我们的中位数。
而中位数无非就是比它大或者比它小,所以我们可以定义比它大的全值为1,比它小的全值为0。
用类似最大字段和的方法来判断是否合法。
代码
点击查看代码
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=3e5+5;
int n;
int a[maxn],b[maxn];
bool check(int x)
{
int cnta=0,cntb=0,cnt=0;
for (int i=1;i<=n;i++)
{
if(a[i]>=x) cnta++;
if(b[i]>=x) cnt++;
if(a[i]>=x) cnt--;
cntb=max(cntb,cnt);
cnt=max(cnt,0ll);
}
return cnta+cntb>=(n+1)/2;
}
signed main()
{
freopen("card.in","r",stdin);
freopen("card.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i]>>b[i];
int l=1,r=inf,ans=0;
while (l<=r)
{
int mid=(l+r)>>1;
if(check(mid)) l=mid+1,ans=mid;
else r=mid-1;
}
cout<<ans<<endl;
return 0;
}
T2
为了方便后续处理,我们假设小的为 \(a\),大的为 \(b\)。
那么接下来就相当于讨论两条线段的相对位置及其交换之后的关系。
可以发现。只有当两个完全不相交时这个式子才会增长。
所以我们只需要找到最小的 \(a\) 和最大的 \(b\) 即可。
代码
点击查看代码
#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],b[maxn],n;
int f(int i,int j)
{
return -abs(a[i]-b[i])-abs(a[j]-b[j])+abs(a[i]-b[j])+abs(b[i]-a[j]);
}
void solve()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) cin>>b[i];
int ans=0;
for(int i=1;i<=n;i++) ans+=abs(a[i]-b[i]);
int sum=ans;
int mini=1,minj=1;
for(int i=1;i<=n;i++)
{
if(max(a[i],b[i])<max(a[mini],b[mini])) mini=i;
if(min(a[i],b[i])>min(a[minj], b[minj])) minj=i;
}
for(int i=1;i<=n;i++)
{
ans=max(ans,sum+f(i,mini));
ans=max(ans,sum+f(i,minj));
}
cout << ans << "\n";
}
signed main()
{
freopen("absolute.in","r",stdin);
freopen("absolute.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int t;cin>>t;
while(t--) solve();
return 0;
}
T3
对于正负号是好考虑的
所以,我们考虑不考虑正负号。
那么它就是一个简单的差分
然后我们再用 \(x+y\) 来给它分类。那么我们再按对角线和反对角线再做一次差分然后对边界进行特殊处理即可。
代码
点击查看代码
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=3005;
const int mod=998244353;
int n,m,k,x,y;
int c,d;
int c1[2][maxn+5][maxn+5],c2[2][maxn+5][maxn+5],c3[2][maxn+5],c4[2][maxn+5];
void solve(int x,int y,int c,int d)
{
int now=(x^y)&1;
int e=c%d,b=c/d;
if(y-b>=1)c1[now][x][y-b]+=e;
else
{
int t=b-y;
if(x-t>=1) c3[now][x-t]+=e;
else c3[now][1]+=e;
c3[now][x+1]-=e;
if(x-t-1>=1) c1[now][x-t-1][1]+=e;
}
if(y-b+1>=1) c1[now][x][y-b+1]+=d-e;
else
{
int t=b-y-1;
if(x-t>=1) c3[now][x-t]+=d-e;
else c3[now][1]+=d-e;
c3[now][x+1]-=d-e;
if(x-t-1>=1) c1[now][x-t-1][1]+=d-e;
}
if(x-b-1>=1) c1[now][x-b-1][y+1]-=e;
else
{
int t=x-b-1;
if(y+t+1>=1) c4[now][y+t+1]+=e;
else c4[now][1]+=e;
c4[now][y+1]-=e;
}
if(x-b>=1) c1[now][x-b][y+1]-=d-e;
else
{
int t=x-b;
if(y+t+1>=1) c4[now][y+t+1]+=d-e;
else c4[now][1]+=d-e;
c4[now][y + 1]-=d-e;
}
if(x+b+1<=n) c1[now][x+b+1][y+1]+=e;
else
{
int t=x+b+1-n;
if(y+t+1<=m) c1[now][n][y+t+1]+=e;
}
if(x+b<=n) c1[now][x+b][y+1]+=d-e;
else
{
int t=x+b-n;
if(y+t+1<=m) c1[now][n][y+t+1]+=d-e;
}
if(y+b+2<=m) c1[now][x][y+b+2]-=e;
if(y+b+1<=m)c1[now][x][y+b+1]-=d-e;
if(y-b>=1) c2[now][x+1][y-b]-=e;
else
{
int t = y-b;
c3[now][x+1]-=e;
if(x-t+2<=n) c3[now][x-t+2]+=e;
if(x-t+2<=n) c2[now][x-t+2][1]-=e;
}
if(y-b+1>=1)c2[now][x+1][y-b+1]-=d-e;
else
{
int t=y-b+1;
c3[now][x+1]-=d-e;
if(x-t+2<=n) c3[now][x-t+2]+=d-e;
if(x-t+2<=n) c2[now][x-t+2][1]-=d-e;
}
if(x-b>=1)c2[now][x-b][y+1]-=e;
else
{
int t=x-b;
c4[now][y+1]-=e;
if(y-t+2<=m) c4[now][y-t+2]+=e;
if(y-t+2<=m) c2[now][1][y-t+2]-=e;
}
if(x-b+1>=1) c2[now][x-b+1][y+1]-=d-e;
else
{
int t=x-b+1;
c4[now][y+1]-=d-e;
if(y-t+2<=m) c4[now][y-t+2]+=d-e;
if(y-t+2<=m) c2[now][1][y-t+2]-=d-e;
}
if(y+b+2<=m) c2[now][x+1][y+b+2]+=e;
if(y+b+1<=m) c2[now][x+1][y+b+1]+=d-e;
if(x+b+2<=n) c2[now][x+b+2][y+1]+=e;
if(x+b+1<=n) c2[now][x+b+1][y+1]+=d-e;
if(x+y<=b)
c3[now][1]+=c-(x+y)*d,
c3[now][2]-=c-(x+y)*d;
}
signed main()
{
freopen("ripple.in","r",stdin);
freopen("ripple.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n>>m>>k;
for(int i=1;i<=k;i++)
{
int x,y,c,d;cin>>x>>y>>c>>d;
solve(x,y,c,d);
}
for(int l=0;l<=1;l++)
{
for(int j=1;j<=m;j++)
for(int i=1;i<=n;i++)
c1[l][i][j]+=c1[l][i+1][j-1],
c2[l][i][j]+=c2[l][i-1][j-1];
for(int i=1;i<=n;i++)c3[l][i]+=c3[l][i-1];
for(int i=1;i<=m;i++)c4[l][i]+=c4[l][i-1];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
c1[l][i][j]+=c2[l][i][j];
for(int i=1;i<=n;i++) c1[l][i][1]+=c3[l][i];
for(int i=1;i<=m;i++) c1[l][1][i]+=c4[l][i];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
c1[l][i][j]+=c1[l][i-1][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
c1[l][i][j] += c1[l][i][j-1];
}
for(int i=1;i<=n;i++)
{
int res = 0,s = 1;
for(int j=1;j<=m;j++)
{
(s*=233)%=mod;
int now=((c1[1][i][j]-c1[0][i][j])%mod+mod)%mod;
if((i^j)&1) (res+=now*s)%=mod;
else (res+=(mod-now)*s)%=mod;
}
cout<<res<<' ';
}
return 0;
}
T4
会发现,当前一个格子,如果说我对它的八个方向,其它本身都进行一次操作的话,那么它就会按原来的扩大一倍
那么考虑用迭代的思想来做,其实我们就是要来求第0种操作
直接从大的往里面推即可。
代码
点击查看代码
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=3005;
int a[maxn][maxn],b[maxn][maxn];
vector<pair<int,int> > v;
signed main()
{
freopen("switch.in","r",stdin);
freopen("switch.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int n,m;cin>>n>>m;
int nn=1ll<<n,mm=1ll<<m,maxx=max(nn,mm);
for(int i=0;i<nn;i++) for(int j=0;j<mm;j++) cin>>a[i][j];
for(int k=max(n,m)-2;k>=0;k--)
{
int now=1ll<<k;
for(int i=0;i<nn;i++)
for(int j=0;j<mm;j++)
{
b[(i+now)%nn][j]^=a[i][j],
b[(i+now)%nn][(j+now)%mm]^=a[i][j],
b[(i+now)%nn][(j+maxx-now)%mm]^=a[i][j],
b[i][j]^=a[i][j],
b[i][(j+now)%mm]^=a[i][j],
b[i][(j+maxx-now)%mm]^=a[i][j],
b[(i+maxx-now)%nn][j]^=a[i][j],
b[(i+maxx-now)%nn][(j+now)%mm]^=a[i][j],
b[(i+maxx-now)%nn][(j+maxx-now)%mm]^=a[i][j];
}
for(int i=0;i<nn;i++) for(int j=0;j<mm;j++) a[i][j]=b[i][j],b[i][j]=0;
}
for(int i=0;i<nn;i++) for(int j=0;j<mm;j++) if(a[i][j]) v.push_back({i,j});
cout<<v.size()<<"\n";
for(auto now:v) cout<<now.first<<" "<<now.second<<"\n";
return 0;
}
本文来自博客园,作者:Engle_Chen,欢迎转载,转载请注明原文链接:https://www.cnblogs.com/EagleChenzhilong/p/23210580
,感谢阅读!
浙公网安备 33010602011771号