题目链接:A - Kefa and Park
题意:
给定一个有n个节点的树,对其中一些节点进行标记,则标记的节点有猫,节点1是家,其它节点为餐馆。从家出发最多可以到达几个餐馆,如果从家出发经过不超过m个猫的餐馆,则认为可以到达此餐馆,并且餐馆没有猫。如果路过有>=m个猫,则到达不了下面的餐馆。
思路:
运用Dfs从1几点向下走,全部走完可以求出可以去多少个餐馆。
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<string>
using namespace std;
const int N =100010;
int a[N];
bool vis[N];
vector<int>ve[N];
int n,m;
int ans;
int Dfs(int u,int count)
{
vis[u]=1;
if(count>m) return 0;
int flag=0;
for(int i=0;i<ve[u].size();i++)
{
int t=ve[u][i];
if(vis[t]==0)
{
flag=1;
if(a[t]==1) Dfs(t,count+1);
else Dfs(t,0);
}
}
if(flag==0) ans++;
}
int main()
{
while(cin>>n>>m)
{
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n-1;i++)
{
int a,b;
cin>>a>>b;
ve[a].push_back(b);
ve[b].push_back(a);
}
ans=0;
Dfs(1,a[1]);
cout<<ans<<endl;
}
return 0;
}
这是一道水题,总结规律即可。
//#include<bits/stdc++.h>
#include<iostream>
using namespace std;
typedef long long ll;
ll a[1110];
int main()
{
int n;
cin>>n;
a[1]=1;
for(int i=2;i<=n;i++)
a[i]=a[i-1]+4*(i-1);
cout<<a[n]<<endl;
}
题意:
给定一个数组,每一个元素可以变化a[i]=-a[i]-1;,求得所有元素乘积的最大值,问此时每一个元素的值是多少?
第一种方法:
思路:
定义一个struct储存 变量值和小标
先将所有元素的负数转化为正数,按数值大小进行排序。
讨论n的奇偶性,如果是奇数,将1~n-1转化为负数
在按下标排序之后进行输出
如果是偶数
将所有的正数都转化为负数按下标排序之后输出就可以了
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
int x;
int id;
}r[100010];
int cmp1(node a,node b)
{
return a.x<b.x;
}
int cmp2(node a,node b)
{
return a.id<b.id;
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>r[i].x;
if(r[i].x<0) r[i].x=-r[i].x-1;
r[i].id=i;
}
sort(r+1,r+n+1,cmp1);
if(n&1)
{
for(int i=1;i<n;i++)
r[i].x=-r[i].x-1;
sort(r+1,r+n+1,cmp2);
for(int i=1;i<=n;i++)
{
if(i==1) cout<<r[i].x;
else cout<<" "<<r[i].x;
}
}
else
{
for(int i=1;i<=n;i++)
r[i].x=-r[i].x-1;
sort(r+1,r+1+n,cmp2);
for(int i=1;i<=n;i++)
{
if(i==1) cout<<r[i].x;
else cout<<" "<<r[i].x;
}
}
cout<<endl;
return 0;
}
第二种方法:
思路:
将所有的非负数转化为负数,记录最小值得位置。
如果n是奇数,将最小值转化为正数就OK了
如果n是偶数,全部输出即可。
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 100010;
int a[N];
int main()
{
int n;
while(cin>>n)
{
int minx=1e7;
int id;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(a[i]>=0) a[i]=-a[i]-1;
if(a[i]<=minx)
{
id=i;
minx=a[i];
}
}
if(n&1)
{
for(int i=1;i<=n;i++)
{
if(i==id)
cout<<-a[i]-1<<" ";
else
cout<<a[i]<<" ";
}
}
else
{
for(int i=1;i<=n;i++)
{
if(i==1) cout<<a[i];
else cout<<" "<<a[i];
}
}
cout<<endl;
}
return 0;
}
题意:
给定一个大小为n的数组,每次取前两个数,将大的那一个数放在第一个,小的那一个数放在最后一个。
思路:
运用 #include<deque
对队列可以进行队首和队尾的相应操作。
#include<iostream>
#include<algorithm>
#include<deque>
using namespace std;
const int N = 100010;
typedef long long ll;
deque<ll>deq;
ll a[N];
ll n,m,maxn=0,num=0;
struct node{
ll l,r;
}r[N];
void Solve()
{
while(true)
{
ll x=deq.front();deq.pop_front();
ll y=deq.front();deq.pop_front();
if(x!=maxn)
{
num++;
r[num].l=x,r[num].r=y;
if(x>y)
{
deq.push_front(x);
deq.push_back(y);
}
else
{
deq.push_front(y);
deq.push_back(x);
}
}
else
{
deq.push_front(y);
for(int i=1;i<=n-1;i++)
{
y=deq.front();deq.pop_front();
a[i]=y;
}
break;
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
ll x;
cin>>x;
deq.push_back(x);
maxn=max(x,maxn);
}
Solve();
while(m--)
{
ll c;
cin>>c;
if(c<=num) cout<<r[c].l<<" "<<r[c].r<<endl;
else
{
c-=num;
c=c%(n-1);
if(c==0) c=n-1;
cout<<maxn<<" "<<a[c]<<endl;
}
}
return 0;
}
题意:
有两个序列1~n 和n—1,输入n,a,x,b,y;
给定数n,在第一个序列中是从a~x;
在第二个数列中是从b~y;问是否在变化的某一个过程a==b
思路:
开两个数组,做成一个循环的数值转换
在第一个序列:a[i]=i+1 a[n]=1;例如:1-2-3-4-5-1-2
在第二个序列:b[i]=i-1,b[1]=n;例如:n–n-1–n-2–1--n
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 110;
int a[N];
int b[N];
int main()
{
int n,c,x,d,y;
while(cin>>n>>c>>x>>d>>y)
{
for(int i=1;i<=n;i++) a[i]=i+1;
a[n]=1;
for(int i=1;i<=n;i++) b[i]=i-1;
b[1]=n;
int i,j;
int flag=0;
for(i=c,j=d;(i!=x)&&(j!=y);i=a[i],j=b[j])
{
// cout<<i<<" "<<j<<endl;
if(i==j)
{
flag=1;
break;
}
}
if(i==j) flag=1;
if(flag) puts("Yes");
else puts("No");
}
return 0;
}
题意:
给定数值范围n,给定m对数
现求能否两个数,使得这两个数中都存在于每对数中
思路:
//#include<bits/stdc++.h>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1000100;
int vx[N],vy[N];
int main()
{
int n,m;
int a,b;
int x,y;
cin>>n>>m;
cin>>x>>y;
int x1=0,x2=0;
int y1=0,y2=0;
memset(vx,0,sizeof(vx));
memset(vy,0,sizeof(vy));
for(int i=1;i<m;i++)
{
cin>>a>>b;
if(a==x||b==x) x1++;
else
{
vx[a]++;
vx[b]++;
x2=max(x2,max(vx[a],vx[b]));
}
if(a==y||b==y) y1++;
else
{
vy[a]++;
vy[b]++;
y2=max(y2,max(vy[a],vy[b]));
}
}
if(x1+x2+1==m||y1+y2+1==m) puts("Yes");
else puts("No");
return 0;
}
题意:
给定n,m;并且大小为n的数组中的每一个元素<m,每一个数都可以转化一次为a[i]=(a[i]+1)%m,问所有元素转化的最多的次数可以使该数组是递增的?//次数最少
思路:
利用二分算法,每一个数最多转化为m次,一定有一次满足此条件
#include<iostream>
#include<algorithm>
using namespace std;
int n,m;
const int N =1000100;
int a[N];
bool check(int x)
{
int pre;
if(a[1]+x<m) pre=a[1];
else pre=0;
for(int i=2;i<=n;i++)
{
int res=-1;
if(a[i]+x>=m&&(a[i]+x)%m>=pre) res=pre;
else if(a[i]<=pre&&a[i]+x>=pre) res=pre;
else if(a[i]>pre) res=a[i];
pre=res;
if(res==-1) return 0;
}
return 1;
}
int main()
{
while(cin>>n>>m)
{
for(int i=1;i<=n;i++) cin>>a[i];
int l=0,r=m;
while(l<r)
{
int mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
cout<<l<<endl;
}
return 0;
}