10.15 2025多校CSP模拟赛5
如此如此,如何如何
T1 小 Z 爱计数(count)
黔岛题
初始值为 \(0\),有三种操作:$ +1,-1,reset $
给定 \(n\) 个二元组 \((a_i,b_i)\) 表示操作 $ a_i $ 次后值为 \(b_i\)
判断是否有一种操作序列满足所有二元组限制
按 $ a_i $ 排序后判一下奇偶性即可
code
#include<bits/stdc++.h>
using namespace std;
const int inf=1e6+10;
int t,n,c;
pair<int,int> e[inf];
inline void sol(){
cin>>c>>n;
for(int i=1;i<=n;i++) cin>>e[i].first>>e[i].second;
sort(e+1,e+1+n);
for(int i=1,da,db;i<=n;i++){
// cout<<i<<'\n';
da=e[i].first-e[i-1].first,db=e[i].second-e[i-1].second;
if(abs(e[i].second)<da) continue;
if(db==0){
if(da%2==1){
cout<<"No\n";
return ;
}
continue;
}
if(da<abs(db)){
cout<<"No\n";
return ;
}
if((da-abs(db))%2==1){
cout<<"No\n";
return ;
}
}
cout<<"Yes\n";
}
signed main(){
#ifndef LOCAL
freopen("count.in","r",stdin);
freopen("count.out","w",stdout);
#else
freopen("count2.in","r",stdin);
freopen("a.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);
cin>>t;
while(t--) sol();
}
/*
*/
T2 小 Z 爱划分(partition)
有趣$ DP $
定义区间 $ [l,r] $ 权值为 \((a_l \oplus a_{l+1} \dots a_r)\)
定义序列 $ a $ 的一组划分 $ [l_1,r_1],[l_2,r_2],\dots,[l_k,r_k] $ 的权值为所有 $ [l_i,r_i] $ 的权值之积
求序列 $ a $ 所有划分的权值平方和
对 $ 10^9+7 $ 取模
$ \sum n \leq 2 \times 10^5 $
赛时想到了神秘 $ O(n^3) $ 式子
表示前 $ i $ 个元素,划分为 $ k $ 个区间的贡献
结果是去掉第二维也是对的……
正解
因为有异或,考虑拆位
在没有什么优化思路的时候,可以试着先思考一个弱化的问题
简化问题
考虑去掉平方
$ s_i $ 为异或前缀和
考虑拆位
$ len $ 表示二进制表示下最大位数
$ o(t)2 $ 表示 $ o $ 在二进制表示下的第 $ t $ 位
记 $ w $ 表示满足 $ s_k(t)_2=c $ 的所有 $ f_k $ 之和
光翼平方展开
同理,$ DP $式子就变为
设 $ w_{p,q,x,y} $ 表示满足 $ s_k(p)_2=x \land s_k(q)_2=y $ 的 $ f_k $ 的和
时间复杂度 $ O(\sum n \log^2 a_i) $
code
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int inf=2e5+10;
const int mod=1e9+7;
int t,n;
int a[inf];
int e[60];
int s[inf],f[inf],w[30][30][2][2];
inline void sol(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) s[i]=s[i-1]^a[i];
memset(w,0,sizeof w);
memset(f,0,sizeof f);
f[0]=1;
for(int i=0;i<=n;i++){
for(int p=0;p<30;p++)
for(int q=0;q<30;q++)
(f[i]+=e[p+q]*w[p][q][!((s[i]>>p)&1)][!((s[i]>>q)&1)]%mod)%=mod;
for(int p=0;p<30;p++)
for(int q=0;q<30;q++)
(w[p][q][(s[i]>>p)&1][(s[i]>>q)&1]+=f[i])%=mod;
// cout<<f[0]<<'\n';
}
cout<<f[n]<<'\n';
}
signed main(){
#ifndef LOCAL
freopen("partition.in","r",stdin);
freopen("partition.out","w",stdout);
#else
freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);
e[0]=1;
for(int i=1;i<60;i++) e[i]=e[i-1]*2%mod;
cin>>t;
while(t--) sol();
}
/*
*/
T3 小 Z 爱优化(opti)
有 $ n $ 个元素,第 $ i $ 个对应权值 $ a_i $
相邻元素自由分组,每组元素个数为 $ 1 $ 或 $ 2 \(\
定义一组的权值为组内元素的权值之和,求极差的最小值\
\) n \leq 2 \times 10^5 $
转化问题:
我们将所有 $ a_i $ 以及 $ a_i+a_{i+1} $ 看成位置不能移动的长为 $ 1 $ 和 $ 2 $ 的骨牌状物。
设 $ dp_{now,i,j} $ 表示在位置 $ now $,左右有无出格的最大值的最小
我们把序列搬到线段树上,就有
形如 $ (a_i) $ 的组初始化时使 $ f_{id(i),0,0}=a_i $
形如 $ (a_i,a_{i+1}) $ 的组初始化时使 $ f_{id(i),0,1}=f_{id(i+1),1,0}=a_i+a_{i+1} $
合并时
code
#include<bits/stdc++.h>
#define int long long
#define lson (id<<1)
#define rson (id<<1|1)
const int inf=4e5+5;
const int maxn=1e18;
using namespace std;
int T,n;
int tot,ans;
int a[inf];
int f[inf<<2][2][2];
struct jtr{
int i,len,val;
}nod[inf];
inline void pushup(int id){
for(int i=0;i<=1;i++){
for(int j=0;j<=1;j++){
f[id][i][j]=maxn;
for(int k=0;k<=1;k++){
f[id][i][j]=min(f[id][i][j],max(f[lson][i][k],f[rson][k][j]));
}
}
}
}
inline void build(int id,int l,int r){
if(l==r){
f[id][0][0]=a[l];
f[id][0][1]=a[l]+a[l+1];
f[id][1][0]=-maxn;
f[id][1][1]=maxn;
return;
}
int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
pushup(id);
}
inline void update(int id,int l,int r,int pos,int len){
if(l==r){
f[id][0][len==2]=maxn;
return;
}
int mid=(l+r)>>1;
if(pos<=mid) update(lson,l,mid,pos,len);
else update(rson,mid+1,r,pos,len);
pushup(id);
}
inline void solve(){
ans=maxn;
tot=0;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
nod[++tot]={i,1,a[i]};
}
for(int i=1;i<n;i++) nod[++tot]={i,2,a[i]+a[i+1]};
sort(nod+1,nod+tot+1,[](jtr x,jtr y){return x.val<y.val;});
build(1,1,n);
for(int i=1;i<=tot;i++){
if(f[1][0][0]>=maxn) break;
ans=min(ans,f[1][0][0]-nod[i].val);
update(1,1,n,nod[i].i,nod[i].len);
}
cout<<ans<<'\n';
}
signed main(){
#ifndef LOCAL
freopen("opti.in","r",stdin);
freopen("opti.out","w",stdout);
#else
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);
cin>>T;
while(T--) solve();
}
T4 小 Z 爱考试(exam)
咕咕

浙公网安备 33010602011771号