目录
A. Gamer Hemose
题意:Agent有种武器,第种武器的伤害值为。他将面对一个生命值为的敌人。Agent将进行一次或多次攻击,直至敌人死亡。(敌人的生命值小于等于0就死亡。)但是,Agent不能连续两次选择相同的武器。问Agent杀死敌人至少需要用多少次武器。
思路:因为连续两次选同一个武器,所以我们选择最大的和次大的来回选。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxx=1e3+10;
int a[maxx];
int main()
{
int t,n,H;
cin>>t;
while(t--)
{
cin>>n>>H;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
sort(a,a+n);
int s=a[n-1]+a[n-2];
int cnt=H/s;//11/9
int ans=2*cnt;
if((H-s*cnt)>0)
{
if((H-s*cnt)>a[n-1])
{
ans+=2;
}
else
{
ans+=1;
}
}
cout<<ans<<endl;
}
}
B. Hemose Shopping
题意:Hemose有一个由个整数组成的数组。他希望Samez按照非递减的顺序对数组进行排序。并且要求:通过交换元素进行排序。并且每次选择的两个元素的下标和满足:,。问是否可能通过有限次交换操作使得数组排好序?
思路:当n=4,x=3时,【1,2,3,4】中2,3没有办法交换,移动不了。
当n=5,x=3时,【1,2,3,4,5】中3没有办法交换。
序列中存在元素始终无法移动,这部分连续且在中间。和a[n]能交换的最大下标+1是这段的左边界,比这个下标小的都能与它交换。同理,能与a[1]交换的最小下标-1是右边界。如果这段区间的元素与排序后的数组相比不同,则不可能完成非递减排序。
注意:小标不能小于1,大于n
int l=max(1,n-x+1);
int r=min(n,x);
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxx=1e5+10;
int a[maxx];
int b[maxx];
int main()
{
int t,n,x;
cin>>t;
while(t--)
{
cin>>n>>x;
for(int i=1;i<=n;i++)
{
cin>>a[i];
b[i]=a[i];
}
sort(b+1,b+1+n);
int l=max(1,n-x+1);
int r=min(n,x);
int f=0;
for(int i=l;i<=r;i++)
{
if(a[i]!=b[i])
{
f=1;
break;
}
}
if(f==1)
cout<<"NO"<<endl;
else
cout<<"YES"<<endl;
}
}
C. Bakry and Partitioning
题意:
给定一颗有n个带点权结点,以及条边的树。(结点从)。现在要求在至少删去1条边,至多删去条边的情况下能否使得删去边后的森林满足:对于每一个连通块其所有点的点权异或和是否都相等。
思路:
设在不删边的情况下所有点的异或和为sum。
如果,那么删且仅仅删一条边即可保证两个连通块的值相等。
如果:
1.当k=1时,即将树分成两个连通块,假设每个连通块的异或和是a,则,与sum=0冲突。
2.三个及以上连通块的情况:对任意非负整数有:,即:每三个相同权值异或和的连通块可以当成一个连通块。因此只考虑能否形成3个权值异或和相等,并且权值异或和为的连通块即可,即删两条边。
将一个树分成异或和相等的三份:
这个操作通过DFS当前结点和其子树异或和得到。如果递归到某个结点其与其所有子节点的异或和为那么可分割块加1,当可分割块等于3的时候结束。
注意:
存无向图/树的方式
vector<int>g[maxx];
g[a].push_back(b);
g[b].push_back(a);
搜索每一部分子树,递归到叶子节点切割分块,将子节点的值都并到当前节点
else//nt不是当前节点的父节点
{
dfs(nt,now);
a[now]=a[now]^a[nt];
}
a[now]=0,把已经分割出去的块的异或总和置为0,才能不影响第二块,第三块的分割。
if(a[now]==sum)
{
a[now]=0;
cnt++;
}
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxx=1e5+10;
vector<int>g[maxx];
int a[maxx];
int sum,cnt;
int t,n,k;
void init()
{
sum=0;
cnt=0;
for(int i=1;i<=n;i++)
g[i].clear();
}
void dfs(int now,int pre)
{
if(cnt==3)
return;
int nt;
for(int i=0;i<g[now].size();i++)
{
nt=g[now][i];
if(nt==pre)
continue;
else
{
dfs(nt,now);
a[now]=a[now]^a[nt];
}
}
if(a[now]==sum)
{
a[now]=0;
cnt++;
}
}
int main()
{
cin>>t;
while(t--)
{
cin>>n>>k;
init();
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum=sum^a[i];
}
int a,b;
for(int i=1;i<n;i++)
{
cin>>a>>b;
g[a].push_back(b);
g[b].push_back(a);
}
if(sum==0)
{
cout<<"YES"<<endl;
}
else
{
if(k==2)
{
cout<<"NO"<<endl;
}
else
{
dfs(1,0);
if(cnt>=2)
{
cout<<"YES"<<endl;
}
else
{
cout<<"NO"<<endl;
}
}
}
}
}