2024.11.2 2024ICPC成都站
Solved:7/13
Penalty:793
Rank:40
Rank(ucup):152
L. Recover Statistics
输出 50 个 P50、45 个 P95,4 个 P99 和 1 个 P99+1 即可。
#include<bits/stdc++.h> using namespace std; int main(){ ios::sync_with_stdio(0);cin.tie(0); int a,b,c; cin>>a>>b>>c; cout<<100<<'\n'; for(int i=1;i<=50;++i)cout<<a<<' '; for(int i=1;i<=45;++i)cout<<b<<' '; for(int i=1;i<=4;++i)cout<<c<<' '; cout<<c+1<<'\n'; }
A. Arrow a Row
题意:用形如 >—>>> (中间可以有任意多个 -)来构造给定字符串,如果可以输出方案。
简单构造,但是卡了很久。
结论是 a[1],a[n-2],a[n-1],a[n]必须是>,且至少要有一个-。
构造就是先把最后一段连续的>都造出来,再造前面的>。
#include<bits/stdc++.h> using namespace std; typedef pair<int,int> pii; void solve(){ string a; cin>>a; int n=a.size(); if(a[0]=='-'||a[n-1]=='-'||a[n-2]=='-'||a[n-3]=='-'){ cout<<"No\n"; return; } int pos=-1; for(int i=n-4;i>=0;--i)if(a[i]=='-'){pos=i;break;} if(!~pos){ cout<<"No\n"; return; } vector<pii> ans; for(int i=n-1;i>=pos+3;--i)ans.emplace_back(0,i); for(int i=1;i<pos;++i)if(a[i]=='>')ans.emplace_back(i,pos+3); cout<<"Yes "<<ans.size()<<'\n'; for(int i=0;i<ans.size();++i)cout<<ans[i].first+1<<' '<<ans[i].second-ans[i].first+1<<'\n'; } int main(){ ios::sync_with_stdio(0);cin.tie(0); int T; cin>>T; while(T--)solve(); }
G.Expanding Array
题意:给一个序列,每次可以在两个数中间插入它们的按位与、按位或、按位异或。问最多能构造出多少个不同的数。
能构造出的数只有
#include<bits/stdc++.h> using namespace std; typedef pair<int,int> pii; int main(){ ios::sync_with_stdio(0);cin.tie(0); int n; cin>>n; vector<int> a(n); for(int& x:a)cin>>x; set<int> s; s.insert(0); for(int i=0;i<a.size()-1;++i){ s.insert(a[i]); s.insert(a[i+1]); s.insert(a[i]&a[i+1]); s.insert(a[i]|a[i+1]); s.insert(a[i]^a[i+1]); s.insert(a[i]&(a[i]^a[i+1])); s.insert(a[i+1]&(a[i]^a[i+1])); } cout<<s.size()<<'\n'; }
I.Good Partitions
题意:维护一个序列,支持单点修改,查询存在多少个
设所有满足
因此只需支持插入、删除一个数,维护全体的
一开始写了个逆天的 vector 套 set,要枚举约数复杂度达到了
然后改成了线段树维护 gcd,不存在的位置就填 0,复杂度
#include<bits/stdc++.h> using namespace std; typedef pair<int,int> pii; const int N=2e5+5; int d[N]; void init(int n){ for(int i=1;i<=n;++i) for(int j=i;j<=n;j+=i)++d[j]; } #define lc (x<<1) #define rc (x<<1|1) #define mid ((l+r)>>1) int n,q,x,y,a[N],s[N*4]; void bld(int x,int l,int r){ if(l==r){s[x]=a[l]>a[l+1]?l:0;return;} bld(lc,l,mid),bld(rc,mid+1,r); s[x]=__gcd(s[lc],s[rc]); } void upd(int x,int l,int r,int p,int v){ if(l==r){s[x]=v;return;} if(p<=mid)upd(lc,l,mid,p,v); else upd(rc,mid+1,r,p,v); s[x]=__gcd(s[lc],s[rc]); } void solve(){ cin>>n>>q,d[0]=n; for(int i=1;i<=n;++i)cin>>a[i]; if(n==1){ cout<<1<<'\n'; while(q--)cin>>x>>y,cout<<1<<'\n'; return; } bld(1,1,n-1); cout<<d[s[1]]<<'\n'; while(q--){ cin>>x>>y; if(x>1&&a[x-1]>a[x]&&a[x-1]<=y)upd(1,1,n-1,x-1,0); if(x>1&&a[x-1]<=a[x]&&a[x-1]>y)upd(1,1,n-1,x-1,x-1); if(x<n&&a[x]>a[x+1]&&y<=a[x+1])upd(1,1,n-1,x,0); if(x<n&&a[x]<=a[x+1]&&y>a[x+1])upd(1,1,n-1,x,x); a[x]=y; cout<<d[s[1]]<<'\n'; } } int main(){ init(2e5); ios::sync_with_stdio(0);cin.tie(0); int T; cin>>T; while(T--)solve(); }
J. Grand Prix of Ballance
简单模拟,map 乱杀。
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<ll,int> pii; const int N=1e5+5; int n,m,q,op,id,x; pii a[N]; int r[N]; set<pii> e; void solve(){ cin>>n>>m>>q; for(int i=1;i<=m;++i)a[i]={0,i}; memset(r,0,sizeof(int)*(n+1)); e.clear(); int cur=0; while(q--){ cin>>op; if(op==1){ cin>>x; cur=x; } else if(op==2){ cin>>id>>x; if(x!=cur||e.find(pii(id,x))!=e.end())continue; a[id].first-=m-r[x]; e.insert({id,x}),++r[x]; } else{ cin>>id>>x; if(x!=cur||e.find(pii(id,x))!=e.end())continue; e.insert({id,x}); } } sort(a+1,a+m+1); for(int i=1;i<=m;++i)cout<<a[i].second<<' '<<-a[i].first<<'\n'; } int main(){ ios::sync_with_stdio(0);cin.tie(0); int T; cin>>T; while(T--)solve(); }
B. Athlete Welcome Ceremony
题意:一个全是abc的字符串,其中某些位置未定,要求相邻位置不同,多次询问,每次询问限制 a 的数量不超过 x,b 的数量不超过 y,c 的数量不超过 z,求方案数。
先 dp 求出 恰好使用 i 个 a、j 个 b、k 个 c 的方案数,然后三维前缀和。
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<ll,int> pii; const int N=305,mod=1e9+7; int n,q,c[3]; string a; ll f[N][N][N][3],s[N][N][N]; int main(){ ios::sync_with_stdio(0);cin.tie(0); cin>>n>>q>>a,a=" "+a; for(int i=1;i<=n;++i)if(a[i]!='?')++c[a[i]-'a']; f[1][0][0][0]=f[0][1][0][1]=f[0][0][1][2]=1; for(int i=0;i<=n;++i) for(int j=0;i+j<=n;++j) for(int k=0;i+j+k<=n;++k)if(i+j+k>0){ if(a[i+j+k]=='a')f[i][j][k][1]=f[i][j][k][2]=0; if(a[i+j+k]=='b')f[i][j][k][0]=f[i][j][k][2]=0; if(a[i+j+k]=='c')f[i][j][k][0]=f[i][j][k][1]=0; if(i+j+k<n){ (f[i+1][j][k][0]+=f[i][j][k][1]+f[i][j][k][2])%=mod; (f[i][j+1][k][1]+=f[i][j][k][0]+f[i][j][k][2])%=mod; (f[i][j][k+1][2]+=f[i][j][k][0]+f[i][j][k][1])%=mod; } } for(int i=0;i<=n;++i) for(int j=0;j<=n;++j) for(int k=0;k<=n;++k){ if(i+j+k==n)s[i][j][k]=f[i][j][k][0]+f[i][j][k][1]+f[i][j][k][2]; if(i>0)s[i][j][k]+=s[i-1][j][k]; if(j>0)s[i][j][k]+=s[i][j-1][k]; if(k>0)s[i][j][k]+=s[i][j][k-1]; if(i>0&&j>0)s[i][j][k]-=s[i-1][j-1][k]; if(i>0&&k>0)s[i][j][k]-=s[i-1][j][k-1]; if(j>0&&k>0)s[i][j][k]-=s[i][j-1][k-1]; if(i>0&&j>0&&k>0)s[i][j][k]+=s[i-1][j-1][k-1]; s[i][j][k]=(s[i][j][k]%mod+mod)%mod; } while(q--){ int x,y,z; cin>>x>>y>>z; x=min(x+c[0],n),y=min(y+c[1],n),z=min(z+c[2],n); cout<<s[x][y][z]<<'\n'; } }
K. Magical Set
题意:给一个集合,每次可选一个数除掉它的一个非 1 约数,且需保证集合中任何时刻没有相同的数。求最多能操作的次数。
最优方案下每次一定除的一定是质数。因此求出每个数及其所有约数的质因子数量
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<ll,int> pii; const int V=6e5+5,E=3e7+5,inf=0x3f3f3f3f; int s,t,v=0,e=1,fir[V],to[E],nxt[E],w[E],c[E]; inline void adde(int x,int y,int z,int t){ to[++e]=y,nxt[e]=fir[x],fir[x]=e,w[e]=z,c[e]=t; to[++e]=x,nxt[e]=fir[y],fir[y]=e,w[e]=0,c[e]=-t; } int dis[V],q[E]; bool vis[V]; bool spfa(){ memset(dis,63,sizeof(dis)); memset(vis,0,sizeof(vis)); int l=1,r=0; q[++r]=t,dis[t]=0; while(l<=r){ int u=q[l++];vis[u]=0; for(int i=fir[u],v=to[i];i;v=to[i=nxt[i]]){ if(!w[i^1]||dis[v]<=dis[u]+c[i^1])continue; dis[v]=dis[u]+c[i^1]; if(!vis[v])vis[v]=1,q[++r]=v; } } return dis[s]<inf; } int cur[V]; int dfs(int u,int flow){ if(u==t||!flow)return flow; vis[u]=1; int nowf=flow; for(int& i=cur[u];i;i=nxt[i]){ int v=to[i]; if(dis[v]+c[i]!=dis[u]||vis[v])continue; int f=dfs(v,min(w[i],nowf)); w[i]-=f,w[i^1]+=f; if(!(nowf-=f))return flow; } return flow-nowf; } int MCMF(){ int flow=0,res=0; while(spfa()){ memcpy(cur,fir,sizeof(cur)); memset(vis,0,sizeof(vis)); int f=dfs(s,inf); flow+=f,res+=dis[s]*f; }return res; } const int N=305; map<int,int> id; int n,a[N],p[V]; int main(){ ios::sync_with_stdio(0);cin.tie(0); cin>>n; s=++v,t=++v; for(int i=1;i<=n;++i){ cin>>a[i]; if(!id.count(a[i]))id[a[i]]=++v; adde(s,id[a[i]],1,0); for(int j=1;j*j<=a[i];++j)if(!(a[i]%j)){ if(!id.count(j))id[j]=++v; if(!id.count(a[i]/j))id[a[i]/j]=++v; } } for(auto &[x,u]:id){ int tt=x; for(int i=2;i*i<=tt;++i)if(!(tt%i)){ while(!(tt%i))tt/=i,++p[u]; } if(tt>1)++p[u]; adde(u,t,1,0); } for(int i=1;i<=n;++i) for(auto &[x,u]:id) if(!(a[i]%x))adde(id[a[i]],u,1,-(p[id[a[i]]]-p[u])); cout<<-MCMF()<<'\n'; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析