A - Kefa and Park
题意:Kefa要到公园里的餐厅吃饭,也就是图的叶子节点,但是Kefa害怕猫,猫的位置已经给出。其中猫**连续**出现的次数不超过m次,Kefa便可通过这条路,问Kefa能到几个餐厅吃饭。
分析:此题是典型的dfs,遍历所有点即可。(比赛的时候没读懂连续m,加上对dfs不太熟悉就没做出来。。。。)
代码如下:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int maxn=1e5+10;
bool vis[maxn];//标记出现猫的的点
bool dis[maxn];//标记已经走过的的点
vector<int> v[maxn];//存图
int n,m;
int ans=0;
void dfs(int x,int y)
{
int ant=0;
if(vis[x]==1)
y--;
else
y=m;
dis[x]=1;
for(int i=0;i<v[x].size();i++)
if(dis[v[x][i]]==0)
ant++;//ant为v[x][i]当前子节点数
if(y>=0&&ant==0)//当y>=0,且子节点数为0(说明该点为叶子节点),ans++;
ans++;
else if(y>=0)
{
for(int i=0;i<v[x].size();i++)
{
if(dis[v[x][i]]==0)
dfs(v[x][i],y);
}
}
}
int main()
{
int a,b;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&vis[i]);
for(int i=0;i<n-1;i++)
{
scanf("%d%d",&a,&b);
v[a].push_back(b);
v[b].push_back(a);
}
dfs(1,m);
printf("%d\n",ans);
return 0;
}
签到题,关系为a[i]=a[i-1]+(i-1)*4;
代码如下:
#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;
int main()
{
int a[105];
int n;
a[1]=1;
for(int i=2;i<=100;i++)
{
a[i]=a[i-1]+(i-1)*4;
}
scanf("%d",&n);
printf("%d\n",a[n]);
return 0;
}
E. Nick and Array
题意:给n个数,a[ 1..(n-1)..n],每个a[ i ]都可以进行ai:=−ai−1(0次,一次,或者多次操作),求变化后a[ i ]的乘积最大时,输出a[ i ],有多种答案,输出一种即可。
分析:这道题有一些贪心的思想,非负数进行该操作后绝对变大乘积的绝对值也变大。当n为偶数时(乘积为正数),可以将所有的正数进行该操作;当n为奇数时只需要有一个数为正数其他都为负数即可,易当进行该操作变成正数的值是所有a[ i ]中再大的时,那么就将这个数变成正数即可;
代码如下:
#include<cstdio>
#include<algorithm>
#include<string.h>
#include<cstring>
#include<map>
#include<cmath>
using namespace std;
const int maxn=1e5+10;
const int maxn2=1e6+10;
int main()
{
int a[maxn];
int n;
int ans=0;
int ant=0;
int awm=0;
int x=-1,y=-1;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
// printf("a[i] %d\n",a[i]);
if(a[i]>=0&&a[i]>=y)
{
x=a[i];
y=a[i];
}
else if(a[i]<=0&&-1*a[i]-1>=y)
{
x=a[i];
y=-1*a[i]-1;
}
// printf("x %d\n",x);
}
// printf("x %d\n",x);
if(n&1)
{
bool flag=0;
for(int i=0;i<n;i++)
{
if(flag==0&&a[i]==x)
{
if(x<0)
x=-1*x-1;
printf("%d ",x);
flag=1;
}
else if(a[i]>=0)
{
a[i]=-1*a[i]-1;
printf("%d ",a[i]);
}
else
printf("%d ",a[i]);
}
}
else
{
for(int i=0;i<n;i++)
{
if(a[i]>=0)
a[i]=-1*a[i]-1;
printf("%d ",a[i]);
}
}
printf("\n");
return 0;
}
/*
5
-3 -2 -1 1 2
4
0 0 0 0
5
-3 -1 1 2 3
5
-7 4 3 -2 1
*/
F - Valeriy and Deque
(含题解)
G. Circle Metro
题意:a,b坐在两条不同的地铁线上
a 乘坐地铁路线为
1→2→…→n→1→2→…
b 乘坐地铁的路线为
n→(n−1)→…→1→n→(n−1)→…
已知 n a上车车站a,下车车站下,b上车车站b, 下车车站y。
问a,b是否同时待在一个车站(两人同时出站不算)
分析:模拟即可
代码如下:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
int main()
{
int n;
int a,x,b,y;
bool flag=0;
scanf("%d%d%d%d%d",&n,&a,&x,&b,&y);
while(a!=x&&b!=y)
{
a=(a+1)%n;
b=(b-1+n)%n;
if(a==0)
a=n;//取余无法达到n,当a==0时,即为第n站
if(b==0)
b=n;//
if(a==b&&!(a==x&&b==y))
{
flag=1;
break;
}
}
if(flag)
printf("YES\n");
else
printf("NO\n");
return 0;
}
H. Pairs
题意比较容易理解。
分析(自己写的比较复杂一点):首先结构体记录下每个点出现的次数和这个点,然后排序,从最大的开始遍历(剪枝)。记录过程中用map记录下每种情况的个数。
代码如下:
#include<cstdio>
#include<algorithm>
#include<string.h>
#include<cstring>
#include<map>
using namespace std;
typedef pair<int,int> pii;
const int maxn=300000+10;
map<pii,int>q;
int n,m;
struct node{
int id=0;
int sam=0;
}s[maxn];
bool cmp(node x,node y)
{
return x.sam>y.sam;
}
int main()
{
int x,y;
pii rr,pp;
bool flag=0;
int ans=0;
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
scanf("%d%d",&x,&y);
s[x].id=x;
s[y].id=y;
s[x].sam++;
s[y].sam++;
rr.first=x,rr.second=y;
q[rr]++;
}
sort(s,s+n+1,cmp);
if(m&1)
ans=m/2+1;
else
ans=m/2;
for(int i=0;i<n;i++)
{
if(s[i].sam<ans)
break;
for(int j=i+1;j<=n;j++)
{
if(s[j].sam<m-s[i].sam)
break;
rr.first=s[i].id,rr.second=s[j].id;
pp.first=s[j].id,pp.second=s[i].id;
if(s[i].sam+s[j].sam-q[rr]-q[pp]>=m)
{
flag=1;
break;
}
}
if(flag)
break;
}
if(flag)
printf("YES\n");
else
printf("NO\n");
return 0;
}
G. Increasing by Modulo
题意:n个整数最大不超过m,问最少进行多少次操作能使数组非递减
分析:操作的选择可用二分解决,l=0 r=m
#include<cstdio>
#include<algorithm>
#include<string.h>
#include<cstring>
#include<map>
using namespace std;
const int maxn=300000+10;
int n,m;
int a[maxn];
int b[maxn];
bool abc(int x)
{
b[1]=a[1];
if(a[1]+x>=m)
b[1]=0;
for(int i=2;i<=n;i++)
{
if(a[i]>b[i-1])
{
b[i]=a[i];
if(a[i]+x>=m&&(a[i]+x)%m>=b[i-1])
b[i]=b[i-1];
}
else if(a[i]+x>=b[i-1])
b[i]=b[i-1];
else
return false;
}
return true;
}
int main()
{
int mod;
int ans;
int l,r;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
r=m+1;
l=0;
while(l<=r)
{
mod=(l+r)/2;
if(abc(mod))
{
ans=mod;
r=mod-1;
}
else
l=mod+1;
}
printf("%d\n",ans);
return 0;
}