【Codeforces】Educational Codeforces Round 46(Contest 1000)

题目

传送门:QWQ

A:Codehorses T-shirts

题意:

给定一些字符串表示去年和今年的衣服型号大小( XL XXL M...... ),要求用最少的次数把去年的衣服大小改成今年需要的。每次改动只能更改字符,不能增添字符。

分析:

把今年和去年的型号字典序排一下。然后用挨个对上(因为题目保证合法,所以长度一样的数量必定相等)。在字符串长度是1的时候要暴力匹配一下,因为长度为1时有L S M三种东西。

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn=;
string a[maxn], b[maxn], q1[maxn], q2[maxn];
int vis[maxn];
int main(){
int n; scanf("%d",&n);
for(int i=;i<=n;i++) cin>>a[i];
for(int i=;i<=n;i++) cin>>b[i];
sort(a+,a++n);sort(b+,b++n);
int ans=;
for(int i=;i<=n;i++){
if(a[i].length()==) continue;
for(int j=;j<a[i].length();j++)
{
if(a[i][j]!=b[i][j]) ans++;
}
}
int k=;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++){
if(a[i].length()!=||b[j].length()!=) continue;
if(a[i]==b[j] && vis[j]==) {
vis[j]=; k--; break;
}
}
for(int i=;i<=n;i++) if(a[i].length()==) k++;
printf("%d\n",ans+k);
return ;
}

B:Light It Up

 

题意:

给定一个$ 10^18 $ 次方的数轴,在数轴上有一些点表示时间。其中有端点0和M。随着时间的推移,每到一个时间点就改变等的状态。

你可以新插入一个点(或者不插),求插入后总的灯亮的时间。

分析:

显然我插的点肯定是在给的点左一个或右一个·。然后前缀和优化模拟一下。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=;
ll A1[maxn],A2[maxn];
ll M[maxn],maxans;ll sum=;
int main(){
int n;ll m;scanf("%d%I64d",&n,&m);
memset(A1,,sizeof(A1));memset(A2,,sizeof(A2));memset(M,,sizeof(M));
M[]=;M[n+]=m;
for(int i=;i<=n+;i++){
scanf("%I64d",&M[i]);
}
M[n+]=M[n+];
for(int i=;i<=n+;i+=){
A1[i-]=A1[i-];
A1[i]+=A1[i-]+M[i+]-M[i];
}A1[n+]=A1[n+];
for(int i=;i<=n+;i+=){
A2[i-]=A2[i-];
A2[i]+=A2[i-]+M[i+]-M[i];
}
A2[n+]=A2[n+];
for(int i=;i<=n+;i++){
ll ma1,ma2;
if(i%== && M[i]!=M[i-]+){
ma1=A1[i-]-+(A2[n+]-A2[i-]);
ma2=A1[i]-+(A2[n+]-A2[i-]);
}
else if(M[i]!=M[i+]-){
ma1=A1[i-]-+(A2[n+]-A2[i-]);
ma2=A1[i]-+(A2[n+]-A2[i-]);
}
if(i!=) maxans=max(maxans,max(ma1,ma2));
else maxans=ma2;
}
printf("%I64d\n",max(A1[n+],maxans));
return ;
}

C:Covered Points Count

 

题意:

线段覆盖数轴相关

分析:

大力算一下,如果是左端点就ans++,否则ans--

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=;
ll sum[maxn];
struct Node{
ll a;int type;
bool operator < (const Node& b) const{return a<b.a;}
}A[maxn];
int main(){
int n,cnt=;scanf("%d",&n);
ll l,r;
for(int i=;i<=n;i++){
scanf("%I64d%I64d",&l,&r);
A[++cnt].a=l; A[cnt].type=; A[++cnt].a=r+; A[cnt].type=-;
}
sort(A+,A++cnt);
A[].a=A[].a;
int ans=,preans=;
for(int i=;i<=cnt;i++){
preans=ans; ans+=A[i].type;
sum[preans]+=A[i].a-A[i-].a;
}
for(int i=;i<=n;i++){
printf("%I64d ",sum[i]);
}
return ;
}
/*
5
10000000000 20000000000
10 100000000000000000
10 100000000000000000
10 100000000000000000
10 100000000000000000
*/

D:Yet Another Problem On a Subsequence

 

题意:

如果一个数组$ a_1.......a_k $ 且 $ a_1 = k-1$,辣么这个数组就是好数组。

一个好序列由好序列和(或)好数组组成。

给出一序列,求他有多少子序列是好序列。

分析:

很显然想到组合数计数一下,但不好处理子序列这个问题。

用$ dp[i] $表示以i开头的好序列的数量

然后对于每个$ a[i] $更新$ dp $

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2000l;const ll MOD=;
ll C[maxn][maxn], a[maxn], dp[maxn];
int main(){
int n;scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%I64d",&a[i]); for(int i=;i<=n+;i++)
for(int j=;j<=n+;j++){
if(j==) C[i][j]=i;
else C[i][j]=(C[i-][j]+C[i-][j-])%MOD;
} dp[n+]=;
for(int i=n-;i>=;i--){
if(a[i]<= || a[i]+i>n) continue;
for(int j=i+a[i]+;j<=n+;j++){
dp[i]=(dp[i]+C[j-i-][a[i]]*dp[j])%MOD;
}
} ll ans=;
for(int i=;i<=n;i++){
ans=(ans+dp[i])%MOD;
}
printf("%I64d\n",ans);
return ;
}

E:We Need More Bosses

 

题意:

求一张图桥最多的路径上桥的数量

分析:

缩点后求树的直径

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn=;
struct Edge{ int u,v; };
vector<Edge> edges; vector<int> G[maxn], g[maxn];
int n, m ;
void Addedge(int a,int b){
edges.push_back((Edge){a,b}); edges.push_back((Edge){b,a});
int m=edges.size(); G[a].push_back(m-);G[b].push_back(m-);
}
int dfs_clock, low[maxn], pre[maxn], q[maxn], fron, scc_cnt, scc[maxn];
int dfs(int u,int fa){
int lowu=pre[u]=++dfs_clock;
q[++fron]=u;
for(int i=;i<G[u].size();i++){
int v=edges[G[u][i]].v, lowv;
if(u==fa) continue;
if(!pre[v]){
lowv=dfs(v,u); lowu=min(lowu,lowv);
// if(lowv>=pre[u]){ ok[G[u][i]]=1; ok[G[u][i]^1]=1;}
}
else{
if(pre[v]<pre[u] && v!=fa) lowu=min(lowu,pre[v]);
}
}
low[u]=lowu;
if(pre[u]==low[u]){
scc_cnt++;
for(;;){
int x=q[fron--]; scc[x]=scc_cnt;
if(x==u) break;
}
}
return lowu;
}
queue<int> que;
int dis[maxn], inq[maxn];
void dist(int x,int f){
dis[x]=dis[f]+;
for(int i=;i<g[x].size();i++){ int v=g[x][i]; if(v==f) continue;//printf("============ %d\n",v);
dist(v,x);
}
}
int main(){
scanf("%d%d",&n,&m);
int x,y;
for(int i=;i<=m;i++){
scanf("%d%d",&x,&y); Addedge(x,y);
}
dfs(,-);
for(int i=;i<edges.size();i++){
Edge e=edges[i];
// printf("--------- %d %d\n",scc[e.u],scc[e.v]);
if(scc[e.u]!=scc[e.v]) g[scc[e.u]].push_back(scc[e.v]);
}
dist(,);int mx=,mp=;
for(int i=;i<=scc_cnt;i++){
if(dis[i]>mx) mx=dis[i],mp=i;
}
memset(dis,,sizeof(dis));
dist(mp,); mx=;
for(int i=;i<=scc_cnt;i++) mx=max(mx,dis[i]);
printf("%d\n",mx-);
return ;
}
上一篇:Codeforces 140D - New Year Contest


下一篇:51nod 1766 树上的最远点对 | LCA ST表 线段树 树的直径