CF#403(Div.2) 解题报告
来源:互联网 发布:mac电脑的使用教程 编辑:程序博客网 时间:2024/05/17 05:57
A
题意简述
有2n双袜子,编号为1..n。
按顺序从包中拿出,如果这只袜子的另一只还没有拿出,就放在桌子上,否则将桌子上的另一只拿走。
求桌子上最多有多少只袜子。
数据范围
题解
模拟。。
代码
#include<algorithm>#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<queue>#include<ctime>#include<cmath>#include<map>using namespace std;int n,x,now,ans;int cnt[100005];int main(){ scanf("%d",&n); for (int i=1;i<=2*n;++i) { scanf("%d",&x); if (!cnt[x]) { ++now; ++cnt[x]; } else --now; ans=max(ans,now); } printf("%d\n",ans);}
B
题意简述
有n个人,站在一个数轴上,位置分别为x1..xn。
每个人有一个速度v1..vn,他可以向左走或者向右走。
求所有的人走到同一个点的最短时间(注意这个点不一定是整点)。
special judge 相对误差不超过
数据范围
题解
实数二分时间mid
每一个人在mid的时间里能走到的范围是一段区间
判断n个区间是否有交集即可
代码
#include<algorithm>#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<queue>#include<ctime>#include<cmath>#include<map>using namespace std;const double eps=1e-6;int n;double x[60005],v[60005],ans;bool check(double mid){ double Min=1e10,Max=-1e10; for (int i=1;i<=n;++i) { double l=x[i]-v[i]*mid,r=x[i]+v[i]*mid; Min=min(Min,r);Max=max(Max,l); } return Min-Max>eps;}double find(){ double l=0.0,r=1e9,mid,ans=0; while (r-l>eps) { mid=(l+r)/2.0; if (check(mid)) ans=r=mid; else l=mid; } return ans;}int main(){ scanf("%d",&n); for (int i=1;i<=n;++i) scanf("%lf",&x[i]); for (int i=1;i<=n;++i) scanf("%lf",&v[i]); ans=find(); printf("%.12lf\n",ans);}
C
题意简述
一棵树,将其染色,任意有两条边相连的3元组3个点都不能染同一种颜色。
求符合要求的最少的颜色,构造方案。
数据范围
题解
显然答案为度数最大的点的度+1
构造方案的话,显然对于一个点来说,它所有的儿子都不能染相同的颜色,并且这些颜色和他自己以及他父亲的颜色都不能相同
dfs的过程中染色即可
代码
#include<algorithm>#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<queue>#include<ctime>#include<cmath>#include<map>using namespace std;#define N 200005int n,x,y,ans;int d[N],c[N];int tot,point[N],nxt[N*2],v[N*2];void add(int x,int y){ ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;}void dfs(int x,int fa){ int now=0; for (int i=point[x];i;i=nxt[i]) if (v[i]!=fa) { ++now; while (now==c[fa]||now==c[x]) ++now; c[v[i]]=now; } for (int i=point[x];i;i=nxt[i]) if (v[i]!=fa) dfs(v[i],x);}int main(){ scanf("%d",&n); for (int i=1;i<n;++i) { scanf("%d%d",&x,&y); add(x,y),add(y,x); ++d[x];++d[y]; ans=max(ans,d[x]);ans=max(ans,d[y]); } printf("%d\n",ans+1); c[1]=1;dfs(1,0); for (int i=1;i<=n;++i) printf("%d%c",c[i]," \n"[i==n]);}
D
题意简述
有n个队伍,每一个队伍有一个名字,是两个字符串。
现在需要你给每一个队伍的名字一个缩写,这个缩写的方式有两种:1、第一个字符串的前三个字符 2、第一个字符串的前两个字符+第二个字符串的第一个字符。
如果有一个队伍选择了第二种方式,那么不能存在某一个队伍选择的第一个方式和这个队伍的第一个方式相同。
求一种方案使所有队伍的缩写互异。
数据范围
题解
典型的2-sat问题
枚举两支队伍,如果:1、第一种相同,那么必须都选第二种 2、第二种相同,不能同时选第二种 3、第一种和第二种相同,不能同时选第一种和第二种
建图缩点判断可行性
最后dfs构造合法解就行了
代码
#include<algorithm>#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<queue>#include<ctime>#include<cmath>#include<map>using namespace std;#define N 1005int n;char s[N];struct data{char s[10];}str[N][5];int tot,point[N*2],nxt[N*N*8],v[N*N*8];int dfn[N*2],low[N*2],stack[N*2],belong[N*2],ch[N*2],last[N*2],top,dfs_clock,scc;bool flag,vis[N*2];bool check(char *a,char *b){ for (int i=1;i<=3;++i) if (a[i]!=b[i]) return 0; return 1;}void add(int x,int y){ ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;}void tarjan(int x){ dfn[x]=low[x]=++dfs_clock;stack[++top]=x;vis[x]=1; for (int i=point[x];i;i=nxt[i]) if (!dfn[v[i]]) { tarjan(v[i]); low[x]=min(low[x],low[v[i]]); } else if (vis[v[i]]) low[x]=min(low[x],dfn[v[i]]); if (dfn[x]==low[x]) { int now=0;++scc; while (now!=x) { now=stack[top--]; belong[now]=scc; vis[now]=0; } }}void dfs(int x){ vis[x]=1; if (ch[x]==-1) { flag=0; return; } stack[++top]=x;last[x]=ch[x];ch[x]=1; if (x<=n) stack[++top]=x+n,last[x+n]=ch[x+n],ch[x+n]=-1; else stack[++top]=x-n,last[x-n]=ch[x-n],ch[x-n]=-1; for (int i=point[x];i&&flag;i=nxt[i]) if (!vis[v[i]]) dfs(v[i]);}int main(){ scanf("%d",&n); for (int i=1;i<=n;++i) { scanf("%s",s);str[i][1].s[1]=s[0],str[i][1].s[2]=s[1],str[i][1].s[3]=s[2]; scanf("%s",s);str[i][2]=str[i][1];str[i][2].s[3]=s[0]; } for (int i=1;i<=n;++i) for (int j=i+1;j<=n;++j) { if (check(str[i][1].s,str[j][1].s)) add(i,n+i),add(j,n+j); if (check(str[i][2].s,str[j][2].s)) add(n+i,j),add(n+j,i); if (check(str[i][1].s,str[j][2].s)) add(i,j),add(n+j,n+i); if (check(str[i][2].s,str[j][1].s)) add(n+i,n+j),add(j,i); } for (int i=1;i<=n;++i) if (!dfn[i]) tarjan(i); for (int i=1;i<=n;++i) if (belong[i]==belong[n+i]) { puts("NO"); return 0; } for (int i=1;i<=n;++i) { if (ch[i]) continue; memset(vis,0,sizeof(vis)); top=0; flag=1;dfs(i); if (!flag) { for (int j=1;j<=top;++j) ch[stack[j]]=last[stack[j]]; } } puts("YES"); for (int i=1;i<=n;++i) { if (ch[i]==1) for (int j=1;j<=3;++j) putchar(str[i][1].s[j]); else for (int j=1;j<=3;++j) putchar(str[i][2].s[j]); puts(""); }}
E
题意简述
一个n个点m条边的无向图,问是否能用至多k条路径覆盖每一个点,并且每条路径的长度不超过
数据范围
题解
这题就是道神经病题。。
dfs过程中记录每一个点的入栈和出栈两次,保证任意的路径不断
然后计算个数输出就行了
题目中每条路径的长度不超过
代码
#include<algorithm>#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<queue>#include<ctime>#include<cmath>#include<map>using namespace std;#define N 400005int n,m,k,x,y;int tot,point[N],nxt[N],v[N];bool vis[N];int ans[N];void add(int x,int y){ ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;}void dfs(int x){ vis[x]=1;ans[++ans[0]]=x; for (int i=point[x];i;i=nxt[i]) if (!vis[v[i]]) { dfs(v[i]); ans[++ans[0]]=x; }}int main(){ scanf("%d%d%d",&n,&m,&k); for (int i=1;i<=m;++i) { scanf("%d%d",&x,&y); add(x,y),add(y,x); } dfs(1);ans[0]=unique(ans+1,ans+ans[0]+1)-ans-1; int now=1; for (int i=1;i<=k;++i) { if (ans[0]-now+1>=(2*n+k-1)/k) { printf("%d ",(2*n+k-1)/k); for (int j=now;j<=now+(2*n+k-1)/k-1;++j) printf("%d%c",ans[j]," \n"[j==now+(2*n+k-1)/k-1]); now=now+(2*n+k-1)/k; } else if (now<=ans[0]) { printf("%d ",ans[0]-now+1); for (int j=now;j<=ans[0];++j) printf("%d%c",ans[j]," \n"[j==ans[0]]); now=ans[0]+1; } else puts("1 1"); }}
F
题意简述
有一个n个点m条边的有向图,每一条边可能是0或1两种类型。
没有自环,两个点之间也不可能有类型相同的两条边。
构造一个序列,方法是:第一个元素为0,之后的每一次将其复制一遍接到后面然后再将复制的部分取反。
栗子:0,01,0110,01101001…
要求在图上按照这个序列走,问走的路径的最长长度。
如果答案
数据范围
题解
非常强的一道dp。。。
有点类似倍增的思想
f(i,j,k,l)表示走的第一条边类型为i,走的长度为
因为是取反,所以dp的时候每一次要反过来接上
求出f了之后如何统计答案呢?
令p表示当前的答案能到达的点,然后枚举每一个点,如果能到达,再用f去更新下一个p
dp的过程中用bitset加速
代码
#include<algorithm>#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<queue>#include<ctime>#include<cmath>#include<bitset>#include<map>using namespace std;#define N 505int n,m,x,y,z,type;long long ans;bitset <N> f[2][65][N],p,q;int main(){ scanf("%d%d",&n,&m); for (int i=1;i<=m;++i) { scanf("%d%d%d",&x,&y,&z); f[z][0][x][y]=1; } for (int i=1;i<=60;++i) for (int j=1;j<=n;++j) for (int k=1;k<=n;++k) { if (f[0][i-1][j][k]) f[0][i][j]|=f[1][i-1][k]; if (f[1][i-1][j][k]) f[1][i][j]|=f[0][i-1][k]; } for (int i=1;i<=n;++i) if (f[0][60][1][i]) { puts("-1"); return 0; } type=0;ans=0LL;p[1]=1; for (int i=60;i>=0;--i) { q.reset(); for (int j=1;j<=n;++j) if (p[j]) q|=f[type][i][j]; if (q.any()) type^=1,ans+=1LL<<i,p=q; if (ans>1e18) break; } if (ans>1e18) puts("-1"); else printf("%I64d\n",ans);}
- CF#403(Div.2) 解题报告
- CF#384 (Div.2) 解题报告
- CF#386(Div.2) 解题报告
- CF#398(Div.2) 解题报告
- CF#401(Div.2) 解题报告
- CF#410(Div.2) 解题报告
- CF Round 415 Div.2解题报告
- CF #308 Div.2 C题 Vanya and Scales 解题报告
- 0712CF解题报告
- 130720CF解题报告
- 130720CF div2解题报告
- cf 161C 解题报告
- Codeforces Round #149 (Div. 2)解题报告
- Codeforces Round #180 (Div. 2) 解题报告
- Codeforces Round #190 (Div. 2) 解题报告
- Codeforces Round #191 (Div. 2) 解题报告
- Codeforces Round #189 (Div. 2) 解题报告
- Codeforces Round #142 (Div. 2) 解题报告
- 牛客-html&css&js-知识汇总(持续更新)
- 怎么用MindManager记笔记
- Search in Rotated Sorted Array
- BZOJ 2844 albus就是要第一个出场
- canvas
- CF#403(Div.2) 解题报告
- alpha测试与beta的区别
- 利用docker部署wooyun的web应用
- .NET中的异步编程
- 一个新的项目:狼人杀
- 对象和数组的复制
- 兜转数年,老跳成了卖过软件开过店写过APP的电脑老师
- (转载)Java String类型的参数传递问题
- (斯坦福机器学习课程笔记)EM算法