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;
}
}
}
京公网安备 11010502036488号