Loading

【题解】Atcoder Beginner Contest 437(ABC437) A~F

A - Feet

直接代入计算。

#include<bits/stdc++.h>
using namespace std;
int a,b;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>a>>b;
    cout<<a*12+b;
    return 0;
}

B - Tombola

直接模拟即可。

#include<bits/stdc++.h>
using namespace std;
int h,w,n,ans;
int a[110][110],cnt[110];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>h>>w>>n;
    for(int i=1;i<=h;i++){
        for(int j=1;j<=w;j++) cin>>a[i][j];
    }
    for(int i=1;i<=n;i++){
        int q;
        cin>>q;
        for(int i=1;i<=h;i++){
            for(int j=1;j<=w;j++){
                if(a[i][j]==q){
                    cnt[i]++;
                    break;
                } 
            }
        }
    }
    for(int i=1;i<=n;i++) ans=max(ans,cnt[i]);
    cout<<ans;
    return 0;
}

C - Reindeer and Sleigh 2

考虑所有鹿都在雪橇上时,总重量为 \(\sum w_i\),换下第 \(i\) 个鹿,拉力 \(+p_i\),重量 \(-w_i\)

题目要求拉力 \(\ge\) 重力,即总重量 \(-\) 拉力 \(\le0\)。根据刚才推得,换下第 \(i\) 个鹿,总重量 \(-\) 拉力变小 \(w_i+p_i\),则按 \(w_i+p_i\) 从大到小选择拉雪橇的鹿直到该值 \(\le 0\) 即可。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e5+10;
int T,n,sum,ans;
int w[N],p[N],a[N];
bool cmp(int x,int y){
    return x>y;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>T;
    while(T--){
        cin>>n;
        sum=ans=0;
        for(int i=1;i<=n;i++){
            cin>>w[i]>>p[i];
            a[i]=p[i]+w[i];
            sum+=w[i];
        } 
        sort(a+1,a+1+n,cmp);
        for(int i=1;i<=n;i++){
            if(sum<=0) break;
            ans++;
            sum-=a[i];
        }
        cout<<n-ans<<'\n';
    }
    return 0;
}

D - Sum of Differences

先考虑没有绝对值怎么做。对于每个 \(a_i\),都要加 \(m\) 次并减去整个 \(b\) 序列的和 \(\sum b_j\),累加统计答案即可。

接着考虑加上绝对值,则对于 \(>a_i\)\(b_j\),需要取相反数。二分查找 \(b\)\(\le a_i\) 的位置 \(k\),维护 \(b\) 的前缀和,则对于 \(a_i\),其贡献为 \(k\times a_i-sumb_k+sumb_m-sumb_k-(m-k)\times a_i\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e5+10;
const int p=998244353;
int n,m,ans;
int a[N],b[N];
int sumb[N];
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.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];
    sort(b+1,b+1+m);
    for(int i=1;i<=m;i++) sumb[i]=sumb[i-1]+b[i];
    for(int i=1;i<=n;i++){
        int t=upper_bound(b+1,b+1+m,a[i])-b-1;
        int res=(a[i]*t-2*sumb[t]+sumb[m]-a[i]*(m-t))%p;
        ans=(ans+res)%p;
    }
    cout<<ans;
    return 0;
}

E - Sort Arrays

向已有序列后接元素形成新序列,不难想到字典树。按字典序排列即字典树的先序遍历,其中同一层的节点按字典序排列。

接着考虑同一大小的元素,如何让其按给定顺序输出。可以把这些元素合并为一个节点,同时维护每个节点包含的编号,按顺序排列。

使用 map 维护每个节点的出边,以及 vector 维护每个节点包含的编号。

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10;
int n;
int h[N],tot=1;
int a[N],b[N];
map<int,int> G[N];
vector<int> unq[N];
void dfs(int u){
    for(int i=0;i<unq[u].size();i++) cout<<unq[u][i]<<' ';
    for(auto i:G[u]) dfs(i.second);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    h[0]=1;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i]>>b[i];
        int u,v;
        u=h[a[i]];
        if(!G[u].count(b[i])) G[u][b[i]]=++tot;
        v=G[u][b[i]];
        h[i]=v,unq[v].push_back(i);
    } 
    dfs(1);
    return 0;
}

F - Manhattan Christmas Tree 2

定义两点间曼哈顿距离:\(|x_1-x_2|+|y_1-y_2|\)。因此查询点 \((x,y)\) 和某一点 \(i\) 间的曼哈顿距离为 \(|x-X_i|+|y-Y_i|\)

因为绝对值较难维护,所以考虑把绝对值拆掉。

分开考虑前后两个绝对值:\(|x-X_i|=\max(x-X_i,-x+X_i),|y-Y_i|=\max(y-Y_i,-y+Y_i)\)

合并两个最大值得到原式:\(|x-X_i|+|y-Y_i|=\max((x+y)-(X_i+Y_i),(x-y)-(X_i-Y_i),(-x+y)+(X_i-Y_i),(-x-y)+(X_i+Y_i))\)

然后我们就可以开线段树维护 \(X_i\pm Y_i\) 的区间最值了,减法需要区间最小值,加法需要区间最大值。查询时计算出以上四个式子,找最大值。

#include<bits/stdc++.h>
#define int long long 
using namespace std;
const int N=2e5+10;
const int INF=1e18;
int n,q;
int X[N],Y[N];
struct Node{
    int mx1,mx2;
    int mn1,mn2;
    int l,r;
};
struct Segtr{
    Node tr[4*N];
    void push_up(int p){
        tr[p].mx1=max(tr[2*p].mx1,tr[2*p+1].mx1);
        tr[p].mx2=max(tr[2*p].mx2,tr[2*p+1].mx2);
        tr[p].mn1=min(tr[2*p].mn1,tr[2*p+1].mn1);
        tr[p].mn2=min(tr[2*p].mn2,tr[2*p+1].mn2);
    }
    void build(int p,int l,int r){
        tr[p].l=l,tr[p].r=r;
        if(l==r){
            tr[p].mx1=tr[p].mn1=X[l]+Y[l];
            tr[p].mx2=tr[p].mn2=X[l]-Y[l];
            return ;
        }
        int mid=(l+r)/2;
        build(2*p,l,mid);
        build(2*p+1,mid+1,r);
        push_up(p);
    }
    void update(int p,int u,int x,int y){
        if(tr[p].l==tr[p].r&&tr[p].l==u){
            X[u]=x,Y[u]=y;
            build(p,tr[p].l,tr[p].r);
            return ;
        }
        int mid=(tr[p].l+tr[p].r)/2;
        if(u<=mid) update(2*p,u,x,y);
        else update(2*p+1,u,x,y);
        push_up(p);
    }
    int query(int p,int l,int r,int x,int y){
        int val=-INF;
        if(l<=tr[p].l&&tr[p].r<=r){
            val=max(val,x+y-tr[p].mn1);
            val=max(val,x-y-tr[p].mn2);
            val=max(val,-x-y+tr[p].mx1);
            val=max(val,-x+y+tr[p].mx2);
            return val;
        }
        int mid=(tr[p].l+tr[p].r)/2;
        if(l<=mid) val=max(val,query(2*p,l,r,x,y));
        if(r>mid) val=max(val,query(2*p+1,l,r,x,y));
        return val;
    }
}seg;
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>n>>q;
    for(int i=1;i<=n;i++) cin>>X[i]>>Y[i];
    seg.build(1,1,n);
    while(q--){
        int op;
        cin>>op;
        if(op==1){
            int u,x,y;
            cin>>u>>x>>y;
            seg.update(1,u,x,y);
        }else{
            int l,r,x,y;
            cin>>l>>r>>x>>y;
            cout<<seg.query(1,l,r,x,y)<<'\n';
        }
    }
    return 0;
}
posted @ 2025-12-28 22:40  Seqfrel  阅读(35)  评论(0)    收藏  举报