A:
很明显的贪心,尽可能让每个飞机都炸自己能炸的最大价值的基地。
从大到小枚举基地的价值,然后二分飞机的破坏力,判断大于这个基地防御力的飞机还剩多少个就行了。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1555555; int a[N],n,m; pair<int,int>b[N]; bool cmp(pair<int,int>a,pair<int,int>b){ return a.second>b.second; } int main(){ std::cin.tie(0); cin>>n>>m; for(int i=1;i<=n;i++){ cin>>a[i]; } for(int i=1;i<=m;i++){ cin>>b[i].first; } for(int i=1;i<=m;i++){ cin>>b[i].second; } sort(a+1,a+1+n); sort(b+1,b+1+m,cmp); ll ans=0,now=n+1; for(int i=1;i<=m;i++){ if(b[i].second<=0)break; int x=upper_bound(a+1,a+1+n,b[i].first)-a; if(a[x]>b[i].first&&x<now){ ans+=(now-x)*b[i].second; now=x; } } cout<<ans<<endl; }
B:二进制
一道很有意思的位运算题目,首先我们知道1个数与1个全1的数得到的结果还是他本身,然后1个数或0和异或0也是他本身,那么我们只需要判断经过了n次位运算以后我们只要枚举他的每一位进行了一次什么运算。
每一位都用0和1枚举最后会变成什么情况,如果0是0,1还是0,那么这一位一定是与0,如果0变成1,1还是1,那么就是或运算,如果0变成1,1变成0那么是进行了异或运算,如果0是0,1是1,那么这一位就是与1,这并不会影响结果。
#include<bits/stdc++.h> using namespace std; typedef long long ll; inline int read(){ int s=0,f=1;char c=getchar(); while(c<'0'||c>'9'){ if(c=='-')f=-1;c=getchar(); } while(c>='0'&&c<='9'){ s=(s<<1)+(s<<3)+(c^48);c=getchar(); } return f*s; } const int N=1555555; int a[N],b[N]; int main(){ int n=read(); int AND=(1<<20)-1,XOR=0,OR=0; for(int i=1;i<=n;i++){ a[i]=read(),b[i]=read(); } for(int i=0;i<20;i++){ int x=0,y=1; for(int j=1;j<=n;j++){ int u=(b[j]>>i)&1; if(a[j]==1){ x&=u; y&=u; } else if(a[j]==2){ x|=u; y|=u; } else if(a[j]==3){ x^=u; y^=u; } } if(!x&&!y)AND-=(1<<i); else if(x&&y)OR+=(1<<i); else if(x&!y)XOR+=(1<<i); } printf("3\n1 %d\n2 %d\n3 %d\n",AND,OR,XOR); return 0; }
C:积木
待补充
D:种树
贪心即可,我们能选的最大的值的深度不可能超过总共剪切的枝叶的一半次数,所以对深度小于等于剪切总次数一半的用大剪切法,其余深度超过的用小剪切法,如果答案存在于上面的深度一半时我们对其中的其他枝叶取max和取min并不影响最大的那一条取max,所以只要深度小于等于(m+1)/2的枝叶我们都可以取max.反之深度大于(m+1)/2我们绝对不会取max,因为如果取了一次,那么中途肯定会有一次取min而达不到最大值.
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1555555; int lson[N],rson[N],val[N],deth[N],vis[N],m; void dfs(int u){ if(!lson[u])return ; deth[lson[u]]=deth[rson[u]]=deth[u]+1; dfs(lson[u]);dfs(rson[u]); if(deth[u]>=m){ val[u]=min(val[lson[u]],val[rson[u]]); } else{ val[u]=max(val[lson[u]],val[rson[u]]); } return ; } int main(){ std::cin.tie(0); int n,ans=0; cin>>n; for(int i=1;i<=n;i++){ cin>>lson[i]>>rson[i]; if(lson[i])m++,vis[i]=true; } m=(m+1)/2; for(int i=1;i<=n;i++){ cin>>val[i]; } dfs(1); cout<<val[1]<<endl; }
E:考试
签到题,贪心让所有答案不一样的题目判断为错即可,如果错的超过不一样的数目,则那个也是错的,相减取绝对值即可。
#include<bits/stdc++.h> using namespace std; int a[15555],b[15555]; int main(){ int n,m;cin>>n>>m; for(int i=1;i<=n;i++){ cin>>a[i]; } for(int i=1;i<=n;i++){ cin>>b[i]; if(b[i]!=a[i])m--; } cout<<n-abs(m)<<endl; }
F:项链
循环队列模拟一下即可,把x原来的前后相连,把y的前或后与x相连,再让y与x相连。
转向的话用个计数器,如果是0正向输出,是1则反向输出即可。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1555555; int l[N],r[N]; int main(){ std::cin.tie(0); int n,m;bool flag=true; cin>>n>>m; for(int i=1;i<=n;i++){ l[i]=i-1; r[i]=i+1; } l[1]=n; r[n]=1; for(int i=1;i<=m;i++){ int u,x,y;cin>>u; if(u==1){ cin>>x>>y; if(flag){ r[l[x]]=r[x]; l[r[x]]=l[x]; l[r[y]]=x; r[x]=r[y]; l[x]=y; r[y]=x; } else{ r[l[x]]=r[x]; l[r[x]]=l[x]; r[l[y]]=x; l[x]=l[y]; l[y]=x; r[x]=y; } } else if(u==2){ cin>>x>>y; if(flag){ r[l[x]]=r[x]; l[r[x]]=l[x]; r[l[y]]=x; l[x]=l[y]; l[y]=x; r[x]=y; } else{ r[l[x]]=r[x]; l[r[x]]=l[x]; l[r[y]]=x; r[x]=r[y]; l[x]=y; r[y]=x; } } else if(u==3){ flag^=1; } else{ int now=1; for(int i=1;i<=n;i++){ printf("%d ",now); now=flag?r[now]:l[now]; } printf("\n"); } } }
G:涂***r>签到题不存在10的情况即只有所有的0在1的左边的情况,最少0个0,最多n个0即n+1种情况
#include<bits/stdc++.h> using namespace std; int main(){ int n;cin>>n; cout<<n+1<<endl; }
H:圆
不相交只有2种情况,一种是包含的情况即圆心距小于半径差,另一种是圆心距大于半径和。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1555555; int main(){ int T;cin>>T; while(T--){ ll x1,y1,r1,x2,y2,r2; cin>>x1>>y1>>r1>>x2>>y2>>r2; ll d=(x2-x1)*(x2-x1)+(y2-y1)*(y2-y1); if(d>(r1+r2)*(r1+r2)||d<=min(r1*r1,r2*r2)&&d<(r2-r1)*(r2-r1)){ cout<<"NO"<<endl; } else{ cout<<"YES"<<endl; } } }