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;
        }
    }
}