Codeforces Round #533 (Div. 2)

Codeforces Round #533 (Div. 2)题解 A

题意:
给你一个序列,你可以修改序列中的每个数使其变成一个另一个正整数,如a-->b代价为abs(a-b)
求一个t是的修改后的(abs)(a[i]-t)<=1,求最小代价
题解:
因为a很小枚举即可

#include<bits/stdc++.h> using namespace std; int a[1005]; int main() { int n; scanf("%d",&n); for (int i=1; i<=n; i++) scanf("%d",&a[i]); int ans1=2000000000,ans2=a[n]; for (int t=1; t<=100; t++) { int sum=0; for (int j=1; j<=n; j++) { int zz=2000000000; for (int tt=t-1; tt<=t+1; tt++) if (tt>0) { zz=min(zz,abs(tt-a[j])); } sum+=zz; } if (sum<ans1) { ans1=sum; ans2=t; } } printf("%d %d\n",ans2,ans1); } B

题意:
给一个字符串和k,连续k个相同的字符,可使等级x加1,
例:8 2 aaacaabb 则有aa aa 即x=2。 求最大的x
题解:
O(N)扫一遍,对于每一段统计一下答案

#include<bits/stdc++.h> using namespace std; int n,k; char s[200005]; int sum[10000]; int main() { scanf("%d%d",&n,&k); scanf("%s",s+1); int pre=0,ans=0,len=0;s[n+1]='A'-1; for (int i=1; i<=n+1; i++) { int x=s[i]-'A'+1; if (x!=pre) { sum[pre]+=len/k; //cout<<x<<" "<<sum[x]<<" "<<len/k<<endl; ans=max(ans,sum[pre]); len=1; } else len++; pre=x; } printf("%d\n",ans); return 0; } C

题意:
一个n长的数组每个位置可以填区间l-r的值。
有多少种填法,使得数组每个位置相加的和是3的倍数
题解:
统计一下l到r mod 3为0、1、2的个数 之后DP一下就可以了

#include<bits/stdc++.h> #define N 200005 #define mod 1000000007 using namespace std; long long f[N][4]; int n,l,r; long long a[4]; int main() { scanf("%d%d%d",&n,&l,&r); a[0]=a[1]=a[2]=(r-l+1)/3; int xx=(r-l+1-a[0]*3); if (xx==1) { if (r%3==0) a[0]++; if (r%3==2) a[2]++; if (r%3==1) a[1]++; } else if (xx==2) { a[0]++; a[1]++; a[2]++; if (r%3==0) a[1]--; if (r%3==2) a[0]--; if (r%3==1) a[2]--; } // cout<<" "<<a[0]<<" "<<a[1]<<" "<<a[2]<<endl; f[1][1]=a[1]; f[1][2]=a[2]; f[1][0]=a[0]; for (int i=2; i<=n; i++) { f[i][0]=((f[i-1][0]*a[0]%mod+f[i-1][1]*a[2]%mod)%mod+f[i-1][2]*a[1]%mod)%mod; f[i][1]=((f[i-1][0]*a[1]%mod+f[i-1][1]*a[0]%mod)%mod+f[i-1][2]*a[2]%mod)%mod; f[i][2]=((f[i-1][0]*a[2]%mod+f[i-1][1]*a[1]%mod)%mod+f[i-1][2]*a[0]%mod)%mod; } printf("%lld",f[n][0]); return 0; } D

题意:
给n*m的地图,最多9个人,同时有每个人的扩张次数(我开始以为是直线扩张最大长度。。实际是能连续扩张次数。)
地图上有‘#’,‘.',和数字,数字对应每个人的据点,
从1-n轮流扩张。
地图被扩张完后,输入每个人的据点数目。
题解:
开p个队列,模拟一下就可以了

#include<bits/stdc++.h> using namespace std; int n,m,p; int dx[5]={0,0,-1,1},dy[5]={1,-1,0,0}; struct Node{ int x,y; }; queue<Node> q[20]; int ans[20],speed[20]; char s[1005][1005]; void run(int i) { for (int tt=q[i].size()-1; tt>=0; tt--) { Node nownode=q[i].front(); ans[i]++; q[i].pop(); for (int k=0; k<4; k++) { int xx=nownode.x+dx[k],yy=nownode.y+dy[k]; if (xx<1 || xx>n || yy<1 || yy>m) continue; if (s[xx][yy]=='.') { s[xx][yy]='0'+i; Node newnode={xx,yy}; q[i].push(newnode); } } } } void init() { scanf("%d%d%d",&n,&m,&p); for (int i=1; i<=p; i++) scanf("%d",&speed[i]); for (int i=1; i<=n; i++) { scanf("%s",s[i]+1); for (int j=1; j<=m; j++) { if (s[i][j]=='.' || s[i][j]=='#') continue; int X=s[i][j]-'1'+1; Node newnode={i,j}; q[X].push(newnode); } } } int main() { init(); while (true) { for (int i=1; i<=p; i++) { for (int j=1; (!q[i].empty() && j<=speed[i]); j++) run(i); } int sum=0; for (int i=1; i<=p; i++) sum+=q[i].size(); //cout<<sum<<endl; if (sum==0) break; } for (int i=1; i<=p; i++) printf("%d ",ans[i]); } E

题意:
有 n 个事件,op = 1 表示我可以修改昵称,op = 2 表示一个名为 s_i 的朋友查询我当前的名字。一个朋友是高兴的当且仅当他每次查询我的名字都为 s_i,保证每个朋友至少查询一次我的名字,问最多可以有多少个朋友高兴。

题解:
之前以为只要高兴一次就可以了 后面才发现每次高兴才算高兴

只高兴一次就算高兴的话 可以用网络流写
1.对于每次修改账号的点 从S连一条容量为1的边
2.对于每次查询,从之前的修改向其连一条容量为1的边
3.对于每个人向T连一条容量为1的边

#include<bits/stdc++.h> #define N 1005 #define INF 100000000 using namespace std; int n,m; int ans; int tot1,tot2; map<string,int> mp; struct Edge{ int from,to,cap,flow,pre; }; struct Dinic{ int n,m,s,t,edgenumber; int now[N],dis[N]; bool vis[N]; vector<Edge> edges; void preclear() { edgenumber=0; edges.clear(); memset(now,-1,sizeof(now)); } void AddEdge(int from,int to,int cap) { // cout<<" "<<from<<" "<<to<<" "<<cap<<endl; Edge E1={from,to,cap,0,now[from]}; edges.push_back(E1); now[from]=edgenumber++; Edge E2={to,from,0,0,now[to]}; edges.push_back(E2); now[to]=edgenumber++; } bool BFS() { queue<int> Q; memset(vis,0,sizeof(vis)); memset(dis,-1,sizeof(dis)); Q.push(s); vis[s]=1; while (!Q.empty()) { int x=Q.front(); Q.pop(); //cout<<x<<endl; for (int p=now[x]; p!=-1; p=edges[p].pre) { Edge e=edges[p]; if (!vis[e.to] && e.cap>e.flow) { vis[e.to]=1; dis[e.to]=dis[x]+1; Q.push(e.to); } } } return vis[t]; } int dfs(int x,int a) { if (x==t || a==0) { return a; } int flow=0,f; for (int p=now[x]; p!=-1; p=edges[p].pre) { Edge e=edges[p]; if (dis[e.to]==dis[x]+1 && (f=dfs(e.to,min(a,e.cap-e.flow))) >0) { edges[p].flow+=f; edges[p^1].flow-=f; a-=f; flow+=f; if (a==0) break; } } return flow; } int maxflow(int s,int t) { this -> s=s; this -> t=t; int flow=0; while (BFS()) { //cout<<"shit"<<endl; flow+=dfs(s,INF); } return flow; } }D; int main() { D.preclear(); scanf("%d%d",&n,&m); int pre=-1,prex=0,s,t; tot1=1; s=0; t=1; for (int i=1; i<=n; i++) { int type; scanf("%d",&type); if (type==1) { ++tot1; pre=tot1; prex=1; } else { string ss; if (prex==1) D.AddEdge(s,pre,1); cin>>ss; if (mp.find(ss)==mp.end()) { mp[ss]=++tot1; D.AddEdge(mp[ss],t,1); } if (pre!=-1) D.AddEdge(pre,mp[ss],1); prex=2; } } cout<<D.maxflow(s,t)<<endl; return 0; }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwxgsz.html