Problem A
这是一个sb题,统计一下比较哪个多就好了
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int INF = 0x3f3f3f3f;
char str[200050];
int main(void)
{
int n;
while(~scanf("%d",&n)){
scanf("%s",str);
int l=0;
for(int i=0;i<n;i++){
if(str[i]=='A')l++;
}
if(l<n-l)puts("Danik");
else if(l>n-l)puts("Anton");
else puts("Friendship");
}
return 0;
}
Problem B
很明显2先组成256是最优的,然后剩下的用来组成32
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int INF = 0x3f3f3f3f;
int main(void)
{
LL k2,k3,k5,k6;
while(~scanf("%lld%lld%lld%lld",&k2,&k3,&k5,&k6)){
LL sum=0;
LL nm=min(k2,min(k5,k6));
sum+=nm*(LL)256;
k2-=nm;
nm=min(k2,k3);
sum+=nm*(LL)32;
printf("%lld\n",sum);
}
return 0;
}
Problem C
因为第二种技能保证魔法值使用越多,威力越大,那么只需要枚举第一种技能,根据剩余的魔法值二分第二种技能的使用,答案取最小值即可
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int INF = 0x3f3f3f3f;
struct spell{
LL atk,cost;
}a[200050],b[200050];
int cmp(spell a,spell b){
return a.cost<b.cost;
}
int main(void)
{
LL n,m,k;
while(~scanf("%lld%lld%lld",&n,&m,&k)){
LL x,s;
scanf("%lld%lld",&x,&s);
LL ans=n*x;
a[0].atk=x;
a[0].cost=0;
for(int i=1;i<=m;i++){
scanf("%lld",&a[i].atk);
}
for(int i=1;i<=m;i++){
scanf("%lld",&a[i].cost);
}
for(int i=1;i<=k;i++){
scanf("%lld",&b[i].atk);
}
for(int i=1;i<=k;i++){
scanf("%lld",&b[i].cost);
}
sort(a+1,a+1+m,cmp);
for(int i=0;i<=m;i++){
if(a[i].cost>s)break;
int tar=s-a[i].cost;
int l=1,r=k;
LL mx=0;
while(l<=r){
int mid=(l+r)>>1;
if(b[mid].cost<=tar){
mx=max(mx,b[mid].atk);
l=mid+1;
}
else r=mid-1;
}
if(n-mx<=0)ans=0;
else ans=min(ans,(LL)(n-mx)*a[i].atk);
}
printf("%lld\n",ans);
}
return 0;
}
Problem D
因为不能leap,所以说八个方向能够check的棋子只取决于距king最近的一个,判一下即可
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int INF = 0x3f3f3f3f;
struct node{
char op;
int x,y;
node(){}
node(char a,int b,int c){op=a,x=b,y=c;}
};
vector<node>lr,rl,r,c;
int cmp(node a,node b){
if(a.x!=b.x)return a.x<b.x;
return a.y<b.y;
}
int main(void)
{
int n;
scanf("%d",&n);
int x,y;
scanf("%d%d",&x,&y);
for(int i=1;i<=n;i++){
char str[2];
int xx,yy;
scanf("%s %d %d",str,&xx,&yy);
node p(str[0],xx,yy);
if(xx==x)r.push_back(p);
if(yy==y)c.push_back(p);
if(xx+yy==x+y)lr.push_back(p);
if(yy-xx==y-x)rl.push_back(p);
}
sort(r.begin(),r.end(),cmp);
sort(c.begin(),c.end(),cmp);
sort(rl.begin(),rl.end(),cmp);
sort(lr.begin(),lr.end(),cmp);
int flag=0;
int fl=-1,fr=r.size()+1;
for(int i=0;i<r.size();i++){
if(r[i].y<y)fl=i;
if(r[i].y>y){fr=i;break;}
}
if(fl!=-1)if(r[fl].op=='R'||r[fl].op=='Q')flag=1;
if(fr!=r.size()+1)if(r[fr].op=='R'||r[fr].op=='Q')flag=1;
fl=-1,fr=c.size()+1;
for(int i=0;i<c.size();i++){
if(c[i].x<x)fl=i;
if(c[i].x>x){fr=i;break;}
}
if(fl!=-1)if(c[fl].op=='R'||c[fl].op=='Q')flag=1;
if(fr!=c.size()+1)if(c[fr].op=='R'||c[fr].op=='Q')flag=1;
fl=-1,fr=rl.size()+1;
for(int i=0;i<rl.size();i++){
if(rl[i].y<y)fl=i;
if(rl[i].y>y){fr=i;break;}
}
if(fl!=-1)if(rl[fl].op=='B'||rl[fl].op=='Q')flag=1;
if(fr!=rl.size()+1)if(rl[fr].op=='B'||rl[fr].op=='Q')flag=1;
fl=-1,fr=lr.size()+1;
for(int i=0;i<lr.size();i++){
if(lr[i].x<x)fl=i;
if(lr[i].x>x){fr=i;break;}
}
if(fl!=-1)if(lr[fl].op=='B'||lr[fl].op=='Q')flag=1;
if(fr!=lr.size()+1)if(lr[fr].op=='B'||lr[fr].op=='Q')flag=1;
if(flag)puts("YES");
else puts("NO");
return 0;
}
Problem E
一个联通块内能够同时染色,所以先将联通块缩点,重建后的树保证相邻的两个点颜色不同,考虑以某个点为根,则需要染色的次数为距离它最远的点距离他的距离,设树的直径为 r ,那么
ans=(r+1)/2
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int INF = 0x3f3f3f3f;
int fa[200050];
int co[200050];
int co2[200050];
int vis[200050];
struct edge{
int v,nxt;
}e[400050];
int h[200050];
int siz;
struct ed{
int u,v;
}pre[200050];
void init(){
siz=0;
memset(e,-1,sizeof(e));
memset(h,-1,sizeof(h));
}
void add(int u,int v){
e[siz].nxt=h[u];
e[siz].v=v;
h[u]=siz++;
}
int as=0;
int dfs(int u,int pr){
int h1=0,h2=0;
for(int i=h[u];~i;i=e[i].nxt){
int v=e[i].v;
if(v!=pr){
int h=dfs(v,u)+1;
if(h>h1)h2=h1,h1=h;
else if(h>h2)h2=h;
}
}
as=max(as,h1+h2);
return h1;
}
int main(void)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&co[i]);
}
init();
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&pre[i].u,&pre[i].v);
add(pre[i].u,pre[i].v);
add(pre[i].v,pre[i].u);
}
queue<int>mq;
int cnt=1;
fa[1]=1;
co2[1]=co[1];
vis[1]=1;
mq.push(1);
while(!mq.empty()){
int u=mq.front();
mq.pop();
for(int i=h[u];~i;i=e[i].nxt){
int v=e[i].v;
if(!vis[v]){
vis[v]=1;
if(co[v]==co[u]){
fa[v]=fa[u];
}
else {
fa[v]=++cnt;
co2[cnt]=co[v];
}
mq.push(v);
}
}
}
init();
for(int i=1;i<n;i++){
int u=pre[i].u;
int v=pre[i].v;
if(fa[u]==fa[v])continue;
add(fa[u],fa[v]);
add(fa[v],fa[u]);
}
dfs(1,1);
printf("%d\n",(as+1)/2);
return 0;
}
Problem F
这道题的关键在于知道
(a|b)+(a&b)=a+b
因此c[i]+b[i]=na[i]+∑j=1na[j]∑i=1nc[i]+b[i]=2n∑j=1na[j]
接下来我们就能够求出每个 a[i] ,只需要判定是否合法即可
暴力判是 n2 的,但是我们可以按位考虑,这样是 nlogn 的
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int INF = 0x3f3f3f3f;
LL b[200050];
LL c[200050];
LL a[220045];
LL num[55];
void check(int n,int &flag){
for(int i=1;i<=n;i++){
LL bb=0,cc=0;
for(int j=50;j>=0;j--){
bb<<=1;cc<<=1;
if((1LL<<j)&a[i]){
bb+=num[j];
cc+=(LL)n;
}
else cc+=num[j];
}
if(bb!=b[i])flag=0;
if(cc!=c[i])flag=0;
if(!flag)return ;
}
}
int main(void)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&b[i]);
}
for(int i=1;i<=n;i++){
scanf("%lld",&c[i]);
}
LL sum=0;
for(int i=1;i<=n;i++){
sum+=(b[i]+c[i]);
}int flag=1;
LL csum=sum;
sum/=((LL)2*n);
if(sum*(LL)2*n!=csum)flag=0;
for(int i=1;i<=n;i++){
a[i]=((b[i]+c[i])-sum)/n;
if(a[i]*n!=(b[i]+c[i])-sum)flag=0;
if(a[i]<0)flag=0;
}
memset(num,0,sizeof(num));
if(flag)for(int i=1;i<=n;i++){
LL p=a[i],k=0;
while(p){
if(p&1LL)num[k]++;
p>>=1;
k++;
}
}
if(flag)check(n,flag);
if(flag){
for(int i=1;i<=n;i++)printf("%lld ",a[i]);
}
else puts("-1");
return 0;
}