A. Andryusha and Socks
题意:现在有n对数字,每次拿出一个数字到桌子上,如果这个数字以前就出现过,就把当前数字和以前数字都都拿走,问桌子上最多有多少种袜子
思路:简单模拟
代码:
#include<bits/stdc++.h>
using namespace std;
int n;
int a[100010];
int main(){
int ans=0;
int maxn=-1;
scanf("%d",&n);
for(int i=0;i<2*n;i++)
{
int temp;
scanf("%d",&temp);
if(a[temp]==0)
{
a[temp]++;
ans++;
maxn=max(maxn,ans);
}
else
{
ans--;
}
}
printf("%d\n",maxn);
}
B. The Meeting Place Cannot Be Changed
题意:现在n个人站在一条路上,每个人都有一个坐标和一个速度,现在要让所有人跑到一个点上,问所需最小时间是多少
思路:二分,二分时间,看该时间能不能让所有人跑到某个点,浮点数二分用for循环100次即可提炼精度,不得不说浮点数二分比整数二分好写多了= =
代码:
#include<bits/stdc++.h>
using namespace std;
struct poi{
int x;
int s;
}a[60100];
bool cmp(poi w,poi e)
{
return w.x<e.x;
}
int n;
bool judge(double time)
{
double len=1.0*a[0].x+1.0*time*a[0].s;
for(int i=1;i<n;i++)
{
if(a[i].x<len)
{
len=min(len,1.0*a[i].x+1.0*time*a[i].s);
}
else
{
if(1.0*a[i].x-1.0*time*a[i].s>len)
return false;
}
}
return true;
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i].x);
for(int i=0;i<n;i++)
scanf("%d",&a[i].s);
sort(a,a+n,cmp);
double l=0;double r=1000000000;
for(int i=0;i<100;i++)
{
double mid=(l+r)/2;
if(judge(mid))
r=mid;
else
l=mid;
}
printf("%.7f\n",(l+r)/2.0);
}
C. Andryusha and Colored Balloons
题意:给你一个图,任意点和它所连的点,这些点之间的任意两点的颜色不能相同,问最少要几种颜色,并给出配色方案
思路:DFS,DFS的时候一边更新最少颜色数,一边染色,在DFS的时候,记录该点的颜色和其之前一个点的颜色会好写一些
代码:
#include<bits/stdc++.h>
using namespace std;
int n;
vector<int> q[200010];
int b[200010];
int ans=0;
void dfs(int now,int fa,int bef,int me)
{
int col=1;
ans=max(ans,(int)q[now].size()+1);
for(int i=0;i<q[now].size();i++)
{
if(q[now][i]!=fa)
{
while(col==bef||col==me)
col++;
b[q[now][i]]=col;
col++;
dfs(q[now][i],now,me,col-1);
}
}
return ;
}
int main(){
scanf("%d",&n);
for(int i=0;i<n-1;i++)
{
int tempa,tempb;
scanf("%d%d",&tempa,&tempb);
q[tempa].push_back(tempb);
q[tempb].push_back(tempa);
}
b[1]=1;
dfs(1,-1,-1,1);
printf("%d\n",ans);
for(int i=1;i<=n;i++)
{
if(i!=1) printf(" ");
printf("%d",b[i]);
}
puts("");
}
D. Innokenty and a Football League
题意:现在有N个队伍,每个队伍的全名有两个部分,现在有给每个队伍起简称,第一种简称是第一个名字的前三位,第二种是第第一个名字的前两位加第二个名字的第一位。每个队伍都想优先使用第一种,但是如果若干个队伍的第一种相同了,那么他们只能使用第二种,如果一个队伍的第一种被占用了,那它也只能使用第二种了
思路:map容器,如果有的队伍第一种名称相同,那么他们都别无选择的使用第二种,如果有个队伍的第一个名字被用了,那他只能用第二种,如果第二个被用了,那他只能用第一种,如果都没有被使用,那就使用第一种。这个题的坑就在,即使两个队伍的第一个名字没有出现重复,也是可能相互制约的,要考虑好优先级才能AC
代码:
#include<bits/stdc++.h>
using namespace std;
map<int,int> mp;//只是用来查看当前字符串以前有没有检查过
map<int,int> mpp;//判断某个名字是否冲突
char a[1010][2][25];//储存原数组串
char ans[1010][3];//储存答案
bool did[1010];//判断是否已经有答案了
int name(int a,int b,int c){return a*10000+b*100+c;}//hash名字
int main(){
int n;
scanf("%d",&n);
bool judge=true;
for(int i=0;i<n;i++) scanf("%s%s",a[i][0],a[i][1]);
for(int i=0;i<n;i++)//用来看当第一种名字相同时,第二种名字是否出现冲突
{
int temp=name(a[i][0][0]-'a',a[i][0][1]-'a',a[i][0][2]-'a');
if(mp[temp]>=1)
continue;
else
{
mp[temp]=1;
for(int j=i+1;j<n;j++)
{
int tempa=name(a[j][0][0]-'a',a[j][0][1]-'a',a[j][0][2]-'a');
if(tempa==temp)
{
mp[temp]=2;
for(int k=i;k<n;k++)
{
int tempb=name(a[k][0][0]-'a',a[k][0][1]-'a',a[k][1][0]-'a');
int tempc=name(a[k][0][0]-'a',a[k][0][1]-'a',a[k][0][2]-'a');
if(tempc==temp){
mpp[tempb]++;
did[k]=true;
ans[k][0]=a[k][0][0]; ans[k][1]=a[k][0][1]; ans[k][2]=a[k][1][0];
if(mpp[tempb]==2){
judge=false;
break;
}
}
}
break;
}
}
}
}
if(judge)
{
bool change=false;
for(int i=0;;i++)//当某个队伍别无选择时,就能确定他的队名,不断循环到没有更新为止
{
if(i==n)
{
i=0;
if(change==0) break;
change=false;
}
int temp=name(a[i][0][0]-'a',a[i][0][1]-'a',a[i][0][2]-'a');
if(mp[temp]==1&&did[i]==0)//第一种队名没重复且名字不确定
{
if(mpp[temp]==1)//第一个名字被用了
{
temp=name(a[i][0][0]-'a',a[i][0][1]-'a',a[i][1][0]-'a');
if(mpp[temp]==1)//第二个也被用了就没办法了
{
judge=false;
break;
}
else{
change=true;
ans[i][0]=a[i][0][0]; ans[i][1]=a[i][0][1];ans[i][2]=a[i][1][0];
did[i]=true;
mpp[temp]++;
}
}
else
{
temp=name(a[i][0][0]-'a',a[i][0][1]-'a',a[i][1][0]-'a');
if(mpp[temp]==1)//第二个被用了就只能用第一个了
{
change=true;
temp=name(a[i][0][0]-'a',a[i][0][1]-'a',a[i][0][2]-'a');
ans[i][0]=a[i][0][0]; ans[i][1]=a[i][0][1]; ans[i][2]=a[i][0][2];
did[i]=true;
mpp[temp]++;
}
}
}
}
if(judge)
{
printf("YES\n");
for(int i=0;i<n;i++)
if(did[i])
printf("%c%c%c\n",ans[i][0],ans[i][1],ans[i][2]);
else
printf("%c%c%c\n",a[i][0][0],a[i][0][1],a[i][0][2]);
}
else
printf("NO\n");
}
else
printf("NO\n");
}
E. Underground Lab
题意:有n个点,m个边,现在有k个起点,每个点最多走
⌈(2∗n)/k⌉
个点,保证有解,求每个点的行动轨迹
思路:DFS,这个题的关键就是要看懂那个向上取整。。。发现是个向上取整的话,就会发现,每个点就算跑两次都能把这个图跑完,那么只要DFS一次,记录下路径,然后分k次输出就好了。。。只能说这个题如果能看懂那个向上取整就毫无难度了,然而我看了题解才看懂。。。。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
vector<int> a[maxn];
bool did[maxn];
int ans[maxn*2];
int cnt=0;
void dfs(int now)
{
did[now]=true;
ans[cnt++]=now;
for(int i=0;i<a[now].size();i++)
{
if(!did[a[now][i]]){
dfs(a[now][i]);
ans[cnt++]=now;
}
}
}
int main(){
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i=0,v,u;i<m;i++)
{
scanf("%d%d",&v,&u);
a[v].push_back(u);
a[u].push_back(v);
}
int step=(2*n+k-1)/k;
dfs(1);cnt--;
for(int i=0;i<k;i++)
{
int l=min(step,cnt+1);
if(l==0)
{
printf("1 1\n");
continue;
}
printf("%d",l);
for(int j=0;j<l&&cnt>=0;j++,cnt--)
printf(" %d",ans[cnt]);
puts("");
}
}