。。只会AB签到

A
就是说对于每个字符为J的位置,如果他同一列下方有I,同一行右边有O,答案就加1
那么直接对每行维护字符O的后缀和,对每列维护I的后缀和 遍历字符集,为J的时候就是两个相乘即可。

#include<bits/stdc++.h>
using namespace  std;
typedef long long ll;
const int maxn=3e3+5;
int n,m;
char a[maxn][maxn];
ll so[maxn][maxn],si[maxn][maxn];
int main(){
    ios::sync_with_stdio(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i]+1;
    for(int i=1;i<=n;i++){
        for(int j=m;j;j--){
            so[i][j]+=so[i][j+1];
            if(a[i][j]=='O') so[i][j]++;
        }
    }
    for(int i=1;i<=m;i++){
        for(int j=n;j;j--){
            si[j][i]+=si[j+1][i];
            if(a[j][i]=='I') si[j][i]++;
        }
    }

    ll ans=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(a[i][j]=='J'){
                ans+=so[i][j]*si[i][j];
            }
        }
    }
    cout<<ans;
    return 0;
}

B
对于画,以美观度为第一关键词降序,美观度一样以大小降序。
对于画框从大到小排序
倒着遍历,如果当前画框大小≥画的大小,则个数加1.
为什么不能正序来呢 如果正序的话,当画框大小不足以装下这幅画,就有个问题了,画主要是按照美观度排序的,可能这个装不下,在后面可能会有更小的画,考虑的较多,比较麻烦。倒序遍历则不需要有这个顾虑,装得下就装,装不下,画就往后移动,因为画框现在的这个就是目前没选择的最大了,不可能去移动画框,只能移动画来判断。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+50;
struct node
{
    int big,v;
    bool friend operator<(node a,node b){
        if(a.v==b.v) return a.big>b.big;
        return a.v>b.v;
    }
}a[maxn];
int b[maxn];
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d%d",&a[i].big,&a[i].v);
    for(int i=1;i<=m;i++) scanf("%d",&b[i]);
    sort(a+1,a+1+n);
    sort(b+1,b+1+m,[](int x,int y){
        return x>y;
    });
    int cnt=0;
    for(int i=1,j=1;i<=n&&j<=m;i++){
        if(b[j]>=a[i].big)
            cnt++,j++;
    }
    printf("%d",cnt);
    return 0;
}