2025多校冲刺省选模拟赛12
2025多校冲刺省选模拟赛12
A. 删除数组
HZTG3024. 发烧(fever)
-
部分分
:模拟。
点击查看代码
const ll mod=1000003579,base=13331; ll jc[100010],a[100010],ans[100010]; unordered_map<ll,ll>cnt,vis; unordered_map<ll,ll>::iterator it; vector<ll>hsh[100010],tmp; char s[100010]; void sx_hash(char s[],ll len) { for(ll i=0;i<=len;i++) a[i]=(i==0)?0:(a[i-1]*base%mod+s[i])%mod; } ll ask_hash(ll l,ll r) { return (a[r]-a[l-1]*jc[r-l+1]%mod+mod)%mod; } int main() { #define Isaac #ifdef Isaac freopen("fever.in","r",stdin); freopen("fever.out","w",stdout); #endif ll n,m,len,i,j,l,r; cin>>n>>m; for(i=0;i<=100000;i++) jc[i]=(i==0)?1:jc[i-1]*base%mod; for(i=1;i<=n;i++) { cin>>(s+1); len=strlen(s+1); tmp.clear(); sx_hash(s,len); for(l=1;l<=len;l++) { for(r=l;r<=len;r++) { hsh[i].push_back(ask_hash(l,r)); tmp.push_back(ask_hash(l,r)); } } sort(tmp.begin(),tmp.end()); tmp.erase(unique(tmp.begin(),tmp.end()),tmp.end()); for(j=0;j<tmp.size();j++) cnt[tmp[j]]++; } for(it=cnt.begin();it!=cnt.end();it++) { if(it->second>=m) vis[it->first]=1; } for(i=1;i<=n;i++) { for(j=0;j<hsh[i].size();j++) ans[i]+=(vis.find(hsh[i][j])!=vis.end()); } for(i=1;i<=n;i++) cout<<ans[i]<<" "; return 0; }
-
正解
- 将子串转化为后缀的一段前缀,考虑后缀数组。
- 考虑双指针维护恰好包含
个来源不同字符串的后缀的区间, 表或单调队列维护 的最小值。- 双指针需要从左右两边各扫一遍维护极短区间。
- 在回退时进行统计答案。特判
的情况。
点击查看代码
ll s[200010],ans[200010],col[200010],cnt[200010]; char t[100010]; deque<ll>q; struct SA { ll sa[200010],rk[400010],oldrk[400010],id[200010],cnt[200010],key[200010],height[200010]; ll val(ll x) { return x; } void counting_sort(ll n,ll m) { memset(cnt,0,sizeof(cnt)); for(ll i=1;i<=n;i++) cnt[key[i]]++; for(ll i=1;i<=m;i++) cnt[i]+=cnt[i-1]; for(ll i=n;i>=1;i--) { sa[cnt[key[i]]]=id[i]; cnt[key[i]]--; } } void init(ll s[],ll len) { ll m=200000,tot=0,num=0; for(ll i=1;i<=len;i++) { rk[i]=val(s[i]); id[i]=i; key[i]=rk[id[i]]; } counting_sort(len,m); for(ll w=1;tot!=len;w<<=1,m=tot) { num=0; for(ll i=len;i>=len-w+1;i--) { num++; id[num]=i; } for(ll i=1;i<=len;i++) { if(sa[i]>w) { num++; id[num]=sa[i]-w; } } for(ll i=1;i<=len;i++) key[i]=rk[id[i]]; counting_sort(len,m); for(ll i=1;i<=len;i++) oldrk[i]=rk[i]; tot=0; for(ll i=1;i<=len;i++) { tot+=(oldrk[sa[i]]!=oldrk[sa[i-1]]||oldrk[sa[i]+w]!=oldrk[sa[i-1]+w]); rk[sa[i]]=tot; } } for(ll i=1,j=0;i<=len;i++) { for(j-=(j>=1);s[i+j]==s[sa[rk[i]-1]+j];j++); height[rk[i]]=j; } } }S; void add(ll x,ll &sum) { if(col[x]!=0) { cnt[col[x]]++; sum+=(cnt[col[x]]==1); } } void del(ll x,ll &sum) { if(col[x]!=0) { cnt[col[x]]--; sum-=(cnt[col[x]]==0); } } struct SMT { struct SegmentTree { ll lazy; }tree[800010]; #define lson(rt) (rt<<1) #define rson(rt) (rt<<1|1) void update(ll rt,ll l,ll r,ll x,ll y,ll val) { if(x<=l&&r<=y) { tree[rt].lazy=max(tree[rt].lazy,val); return; } ll mid=(l+r)/2; if(x<=mid) update(lson(rt),l,mid,x,y,val); if(y>mid) update(rson(rt),mid+1,r,x,y,val); } ll query(ll rt,ll l,ll r,ll pos) { if(l==r) return tree[rt].lazy; ll mid=(l+r)/2; return max(tree[rt].lazy,(pos<=mid)?query(lson(rt),l,mid,pos):query(rson(rt),mid+1,r,pos)); } }T; int main() { #define Isaac #ifdef Isaac freopen("fever.in","r",stdin); freopen("fever.out","w",stdout); #endif ll n,m,len=0,_len,sum=0,i,j; cin>>n>>m; for(i=1;i<=n;i++) { scanf("%s",t+1); _len=strlen(t+1); for(j=1;j<=_len;j++) { len++; s[len]=t[j]-'a'+1; col[len]=i; } len++; s[len]=100000+i; ans[i]=(m==1)*_len*(_len+1)/2; } S.init(s,len); for(i=1,j=1;i<=len&&m!=1;i++) { add(S.sa[i],sum); while(q.empty()==0&&S.height[q.back()]>=S.height[i]) q.pop_back(); q.push_back(i); for(;sum>=m;j++) { if(q.empty()==0&&S.sa[j]==S.sa[q.front()]) q.pop_front();// j+1 ~ i 的最小值 T.update(1,1,len,j,i,S.height[q.front()]); if(sum==m&&cnt[col[S.sa[j]]]==1) break;// 删去后有些情况会统计不到 del(S.sa[j],sum); } } for(i=1;i<=len&&m!=1;i++) ans[col[S.sa[i]]]+=T.query(1,1,len,i); for(i=1;i<=n;i++) cout<<ans[i]<<" "; return 0; }
B. 千岛题
-
部分分
- 由排序不等式,先按照
降序排序,然后做背包 。 - 设
表示前 个数中选择了 个的最小代价,状态转移方程为 。
- 由排序不等式,先按照
:观察到每次修改的都是一段后缀,且分界点前后具有单调性,可以借此来进行剪枝。
点击查看代码
ll f[300010]; pair<ll,ll>c[300010]; int main() { #define Isaac #ifdef Isaac freopen("check.in","r",stdin); freopen("check.out","w",stdout); #endif ll n,m,ans=0,i,j; cin>>n>>m; for(i=1;i<=n;i++) cin>>c[i].second; for(i=1;i<=n;i++) cin>>c[i].first; sort(c+1,c+1+n,greater<pair<ll,ll> >()); memset(f,0x3f,sizeof(f)); f[0]=0; for(i=1;i<=n;i++) { for(j=i;j>=1&&f[j]>f[j-1]+c[i].first*(j-1)+c[i].second;j--) f[j]=f[j-1]+c[i].first*(j-1)+c[i].second; } for(i=n;i>=0;i--) { if(f[i]<=m) { ans=i; break; } } cout<<ans<<endl; return 0; }
- 口胡
-
转移中一段后缀均从
转移过来时可以看做分界点 整体向右覆盖一位,然后权值加上 。不妨将 存储在 节点上,维护 三个懒惰标记,可持久化平衡树支持区间复制,需要定期重构,大概 多次。 -
二分找到分界点,时间复杂度为
,可能会被卡常。 -
进一步优化的做法可能类似 CF573E Bear and Bowling 。
代码还没写完,不写了
ll f[100010]; pair<ll,ll>c[100010]; struct BST { ll root,rt_sum; struct FHQ_Treap { ll son[2],siz,val,id,add,mul,lazy; }tree[6501110]; #define lson(rt) (tree[rt].son[0]) #define rson(rt) (tree[rt].son[1]) ll build_rt() { rt_sum++; lson(rt_sum)=rson(rt_sum)=tree[rt_sum].val=tree[rt_sum].id=tree[rt_sum].add=tree[rt_sum].lazy=0; tree[rt_sum].siz=tree[rt_sum].mul=1; return rt_sum; } ll copy_rt(ll rt) { rt_sum++; tree[rt_sum]=tree[rt]; return rt_sum; } void pushup(ll rt) { tree[rt].siz=tree[lson(rt)].siz+tree[rson(rt)].siz+1; } void pushlazy(ll &rt,ll add,ll mul,ll lazy) { if(add==0&&mul==0&&lazy==0) return; rt=copy_rt(rt); tree[rt].id+=lazy; tree[rt].lazy+=lazy; tree[rt].val+=mul*tree[rt].id+add; tree[rt].add+=add; tree[rt].mul+=mul; } void pushdown(ll rt) { pushlazy(lson(rt),tree[rt].add,tree[rt].mul,tree[rt].lazy); pushlazy(rson(rt),tree[rt].add,tree[rt].mul,tree[rt].lazy); tree[rt].add=tree[rt].lazy=0; tree[rt].mul=1; } void split(ll rt,ll k,ll &x,ll &y) { cerr<<rt<<" "<<k<<" "<<x<<" "<<y<<endl; if(rt==0||k==0) { x=y=0; return; } pushdown(rt); if(tree[lson(rt)].siz+1<=k) { x=copy_rt(rt); split(rson(rt),k-tree[lson(rt)].siz-1,rson(x),y); pushup(x); } else { y=copy_rt(rt); split(lson(rt),k,x,lson(y)); pushup(y); } } ll merge(ll rt1,ll rt2) { if(rt1==0||rt2==0) return rt1+rt2; ll rt; pushdown(rt1); pushdown(rt2); if(rand()%(tree[rt1].siz+tree[rt2].siz)<tree[rt1].siz) { rt=copy_rt(rt1); rson(rt)=merge(rson(rt),rt2); } else { rt=copy_rt(rt2); lson(rt)=merge(rt1,lson(rt)); } pushup(rt); return rt; } void update(ll id,ll b,ll a) { ll l=2,r=id,ans=id,mid,x,y,z,_z; while(l<=r) { mid=(l+r)/2; split(root,mid,x,y); split(x,mid-2,x,z); split(z,1,_z,z); if(tree[z].val>tree[_z].val+(tree[_z].id-1)*b+a) { ans=mid; r=mid-1; } else { l=mid+1; } root=merge(merge(merge(x,_z),z),y); } split(root,ans-1,x,y); y=copy_rt(y); pushlazy(y,a,b,1); root=merge(x,copy_rt(y)); } ll query(ll id) { ll x,y,z,ans; split(root,id+1,x,y); split(root,id,x,z); ans=tree[z].val; root=merge(merge(x,z),y); return ans; } }T; int main() { // #define Isaac #ifdef Isaac // freopen("check.in","r",stdin); // freopen("check.out","w",stdout); freopen("in.in","r",stdin); freopen("out.out","w",stdout); #endif ll n,m,ans=0,i; cin>>n>>m; for(i=1;i<=n;i++) cin>>c[i].second; for(i=1;i<=n;i++) cin>>c[i].first; sort(c+1,c+1+n,greater<pair<ll,ll> >()); T.root=T.build_rt(); for(i=1;i<=n;i++) { T.update(i,c[i].first,c[i].second); } for(i=n;i>=0;i--) { if(T.query(i)<=m) { ans=i; break; } } cout<<ans<<endl; return 0; }
-
-
正解
C. 车
-
部分分
:爆搜。
点击查看代码
ll a[200010],b[200010],c[200010],cnt[200010],ans=0x3f3f3f3f3f3f3f3f; void dfs(ll pos,ll n,ll m) { if(pos==m+1) { ll maxx=0; for(ll i=1;i<=n;i++) maxx=max(maxx,cnt[i]); ans=min(ans,maxx); } else { for(ll i=1;i<=n;i++) cnt[i]+=(a[pos]<=i&&i<=b[pos]-1); dfs(pos+1,n,m); for(ll i=1;i<=n;i++) cnt[i]-=(a[pos]<=i&&i<=b[pos]-1); for(ll i=1;i<=n;i++) cnt[i]+=(i<=a[pos]-1||i>=b[pos]); dfs(pos+1,n,m); for(ll i=1;i<=n;i++) cnt[i]-=(i<=a[pos]-1||i>=b[pos]); } } int main() { #define Isaac #ifdef Isaac freopen("tickets.in","r",stdin); freopen("tickets.out","w",stdout); #endif ll n,m,i; cin>>n>>m; for(i=1;i<=m;i++) { cin>>a[i]>>b[i]>>c[i]; if(a[i]>b[i]) swap(a[i],b[i]); } dfs(1,n,m); cout<<ans<<endl; return 0; }
-
正解
总结
- 无意义罚坐。
后记
暑假模拟赛时出过,遂 把题换了。
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/18714438,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探
2024-02-14 2024寒假自主提升日记