Educational Codeforces Round 55 (Rated for Div. 2)
A.Vasya and Book
三种情况讨论一下
1 #include<bits/stdc++.h> 2 using namespace std; 3 int main() 4 { 5 int _; 6 scanf("%d",&_); 7 while(_--) 8 { 9 int n,d,x,y; 10 scanf("%d%d%d%d",&n,&x,&y,&d); 11 if((n-y)%d!=0&&(x-y)%d!=0&&(y-1)%d!=0) 12 { 13 printf("-1\n"); 14 } 15 else 16 { 17 int s=n; 18 if((y-x)%d==0)s=min(s,abs(y-x)/d); 19 if((n-y)%d==0)s=min(s,(n-y)/d+(n+d-1-x)/d); 20 if((y-1)%d==0)s=min(s,(x+d-2)/d+(y-1)/d); 21 printf("%d\n",s); 22 } 23 } 24 return 0; 25 }
B. Vova and Trophies
把G切开 这样共有k段
针对k的数量分三类处理
1 #include<bits/stdc++.h> 2 using namespace std; 3 char a[100001]; 4 int k,l[100001],r[100001]; 5 int main() 6 { 7 int n; 8 scanf("%d\n",&n); 9 scanf("%s",a); 10 int i=0; 11 while(i<n) 12 { 13 while(i<n&&a[i]!='G')i++; 14 if(i>=n)break; 15 k++; 16 l[k]=i; 17 while(i<n&&a[i]=='G')i++; 18 r[k]=i-1; 19 } 20 int ans=k==0?0:r[1]-l[1]+1+(k>=2); 21 for(i=2;i<=k;i++) 22 { 23 if(l[i]-2==r[i-1])ans=max(ans,r[i]+r[i-1]-l[i]-l[i-1]+3-(k<=2)); 24 else ans=max(ans,r[i]-l[i]+1+(k>=2)); 25 } 26 printf("%d",ans); 27 return 0; 28 }
C. Multi-Subject Competition
如果一个项目能派x人出战,且x人的战斗值之和为正
那么就把它加入到最终每个项目派x人出战的贡献中
最后扫一遍答案
1 #include<bits/stdc++.h> 2 using namespace std; 3 struct node 4 { 5 int c,r; 6 }nu[100001]; 7 bool cmp(node i,node j) 8 { 9 return i.r!=j.r?i.r<j.r:i.c>j.c; 10 } 11 int s[100001]; 12 int main() 13 { 14 int n,m; 15 scanf("%d%d",&n,&m); 16 for(int i=1;i<=n;i++) 17 { 18 scanf("%d%d",&nu[i].r,&nu[i].c); 19 } 20 sort(nu+1,nu+n+1,cmp); 21 int N=0,ss; 22 for(int i=1;i<=n;i++) 23 { 24 if(nu[i].r!=nu[i-1].r){ss=0;N=0;} 25 ss+=nu[i].c; 26 N++; 27 if(ss>0)s[N]+=ss; 28 } 29 int ans=0; 30 for(int i=1;i<=n;i++)ans=max(s[i],ans); 31 printf("%d",ans); 32 return 0; 33 }
D. Maximum Diameter Graph
每个度大于等于2的点在最后的图中一定形成一条链
然后链的头和尾加一个度为1的点(如果有)
构不成图就是度大于等于2的每个点度-2的和小于度为1的点数量-2
1 #include<bits/stdc++.h> 2 using namespace std; 3 vector<int> n0,n1,nx; 4 int main() 5 { 6 int n,s1=0,s2=0,n2=0,x; 7 scanf("%d",&n); 8 for(int i=1;i<=n;i++) 9 { 10 scanf("%d",&x); 11 if(x==1) 12 { 13 n0.push_back(i); 14 s1++; 15 } 16 else 17 { 18 n1.push_back(i); 19 nx.push_back(x-2); 20 s2+=x-2; 21 n2++; 22 } 23 } 24 if(s1>s2+2){printf("NO");return 0;} 25 printf("YES %d\n%d\n",n2+(s1>=1)+(s1>=2)-1,s1+n2-1); 26 if(s1>=1)printf("%d %d\n",n1[0],n0[s1-1]),s1--; 27 if(s1>=1)printf("%d %d\n",n1[n2-1],n0[s1-1]),s1--; 28 int i=0; 29 while(s1) 30 { 31 while(nx[i]==0)i++; 32 nx[i]--; 33 printf("%d %d\n",n1[i],n0[s1-1]); 34 s1--; 35 } 36 for(i=0;i<n2-1;i++) 37 printf("%d %d\n",n1[i],n1[i+1]); 38 return 0; 39 }
E. Increasing Frequency
贪心+最长连续字段和
答案=[l,r]*这一段(众数个数-C个数)+C总的个数
1 #include<bits/stdc++.h> 2 using namespace std; 3 int nc[500001],s[500001]; 4 int pre[500001]; 5 int main() 6 { 7 int n,c,x; 8 int ans=0; 9 scanf("%d%d",&n,&c); 10 for(int i=1;i<=n;i++) 11 { 12 scanf("%d",&x); 13 if(x==c) 14 nc[i]=nc[i-1]+1; 15 else 16 { 17 nc[i]=nc[i-1]; 18 s[x]=max(1,s[x]+1-nc[i]+nc[pre[x]]); 19 pre[x]=i; 20 ans=max(s[x],ans); 21 } 22 } 23 printf("%d",ans+nc[n]); 24 return 0; 25 }
F. Speed Dial
字典树+dp
dp[x][k][fa]表示字典树上以x为根的子树上 可以安排k个按钮 且之前的按钮在fa的位置上
dp2[x][k][fa][s]表示字典树上以x为根的子树上 可以安排k个按钮且x不能被安排为按钮 且之前的按钮在fa的位置上 考虑前s个儿子的子树上可以安排按钮
那么转移就很显然了
dp[x][k][fa]=min(dp[x][k-1][x],dp2[x][k][fa][儿子的数量]+x和fa的距离*当前节点拨号次数)
dp2[x][k][fa][s]=min(dp[第s个儿子][j][fa]+dp2[x][k-j][fa][s-1])(0<=j<=k)
所以记忆化搜索搞一下就好了
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=507,K=11,inf=1e9; 4 struct node 5 { 6 int nxt[10]; 7 int cnt; 8 node() 9 { 10 memset(nxt,-1,sizeof(nxt)); 11 cnt=0; 12 } 13 }trie[N]; 14 int cnt; 15 int h[N]; 16 int n,k; 17 int dp[N][K][N]; 18 int dp2[N][K][N][K]; 19 void add(string s,int m) 20 { 21 int cur=0; 22 for(int i=0;i<s.size();i++) 23 { 24 int x=s[i]-'0'; 25 if(trie[cur].nxt[x]==-1) 26 { 27 trie[cnt]=node(); 28 trie[cur].nxt[x]=cnt; 29 h[cnt]=h[cur]+1; 30 cnt++; 31 } 32 cur=trie[cur].nxt[x]; 33 } 34 trie[cur].cnt+=m; 35 } 36 int work(int x,int k,int fa) 37 { 38 if(dp[x][k][fa]!=-1)return dp[x][k][fa]; 39 vector<int> son; 40 for(int i=0;i<=9;i++) 41 if(trie[x].nxt[i]!=-1) 42 son.push_back(trie[x].nxt[i]); 43 dp[x][k][fa]=inf; 44 if(k>0) 45 dp[x][k][fa]=work(x,k-1,x); 46 dp2[x][k][fa][0]=0; 47 for(int i=1;i<=son.size();i++) 48 { 49 dp2[x][k][fa][i]=inf; 50 for(int j=0;j<=k;j++) 51 dp2[x][k][fa][i]=min(dp2[x][k][fa][i],work(son[i-1],j,fa)+dp2[x][k-j][fa][i-1]); 52 } 53 dp[x][k][fa]=min(dp[x][k][fa],dp2[x][k][fa][son.size()]+(h[x]-h[fa])*trie[x].cnt); 54 return dp[x][k][fa]; 55 } 56 int main() 57 { 58 trie[0]=node(); 59 cnt=1; 60 cin>>n>>k; 61 for(int i=1;i<=n;i++) 62 { 63 string s;int m; 64 cin>>s>>m; 65 add(s,m); 66 } 67 memset(dp,-1,sizeof(dp)); 68 printf("%d",work(0,k,0)); 69 return 0; 70 }
G. Petya and Graph
最大权闭合子图
把每条边都当做一个点 并与其两个顶点连一条容量无穷大的边 与s连一条容量为权值的边
把每个顶点连一条与t容量为权值的边
求s到t的最大流 用边权值的和减去最大流就是答案
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MXE=6000000,MX=1000050; 4 const long long inf=1e15; 5 struct MaxFlow 6 { 7 struct Edge 8 { 9 int v,nxt; 10 long long w; 11 }edge[MXE]; 12 int tot,num,s,t; 13 int head[MX]; 14 void init() 15 { 16 memset(head,-1,sizeof(head)); 17 tot=0; 18 } 19 void add(int u,int v,long long w) 20 { 21 edge[tot].v=v; 22 edge[tot].w=w; 23 edge[tot].nxt=head[u]; 24 head[u]=tot++; 25 edge[tot].v=u; 26 edge[tot].w=0; 27 edge[tot].nxt=head[v]; 28 head[v]=tot++; 29 } 30 int d[MX],vis[MX],gap[MX]; 31 void bfs() 32 { 33 memset(d, 0, sizeof(d)); 34 memset(gap, 0, sizeof(gap)); 35 memset(vis, 0, sizeof(vis)); 36 queue<int>q; 37 q.push(t); 38 vis[t] = 1; 39 while (!q.empty()) 40 { 41 int u=q.front(); 42 q.pop(); 43 for (int i=head[u];~i;i=edge[i].nxt) { 44 int v = edge[i].v; 45 if (!vis[v]) { 46 d[v]=d[u]+1; 47 gap[d[v]]++; 48 q.push(v); 49 vis[v]=1; 50 } 51 } 52 } 53 } 54 55 int last[MX]; 56 long long dfs(int u,long long f) 57 { 58 if (u==t) return f; 59 long long sap=0; 60 for (int i=last[u];~i;i=edge[i].nxt) 61 { 62 int v=edge[i].v; 63 if (edge[i].w>0&&d[u]==d[v]+1) 64 { 65 last[u]=i; 66 int tmp=dfs(v, min(f-sap, edge[i].w)); 67 edge[i].w-=tmp; 68 edge[i^1].w+=tmp; 69 sap+=tmp; 70 if(sap==f)return sap; 71 } 72 } 73 if (d[s]>=num) return sap; 74 if (!(--gap[d[u]])) d[s]=num; 75 ++gap[++d[u]]; 76 last[u]=head[u]; 77 return sap; 78 } 79 80 long long solve(int st,int ed,int n) 81 { 82 long long flow=0; 83 num=n; 84 s=st; 85 t=ed; 86 bfs(); 87 memcpy(last, head, sizeof(head)); 88 while (d[s]<num)flow+=dfs(s,inf); 89 return flow; 90 } 91 }F; 92 int m,n; 93 int main() 94 { 95 scanf("%d%d",&n,&m); 96 int i,x,u,v; 97 F.init(); 98 long long ans=0; 99 for(i=1;i<=n;i++) 100 { 101 scanf("%d",&x); 102 F.add(i,n+m+1,x); 103 } 104 for(i=1;i<=m;i++) 105 { 106 scanf("%d%d%d",&u,&v,&x); 107 F.add(n+i,u,inf); 108 F.add(n+i,v,inf); 109 F.add(0,n+i,x); 110 ans+=x; 111 } 112 printf("%lld",ans-F.solve(0,n+m+1,n+m+2)); 113 return 0; 114 }

浙公网安备 33010602011771号