iwtgm-21

题目链接

A.

首先每个木板最多增加2个高度
设木板a,b,c,若a与b高度相同,那么我们让b高度+1,假设b现在又与c高度相同,那么我们让b的高度再+1
b只有两个相邻木板,所以b不用再改变了
所以当前木板可以有3个选择:不变,高度+1,高度+2
并要保证与前一块木板高度不同,那么我们枚举的时候把这个限制加上

ll a[N],b[N];
ll dp[N][3];
void solve() {
    int n;cin>>n;
    for(int i=0;i<=n;i++){
        if(i==0){
            dp[i][0]=dp[i][1]=dp[i][2]=inf;
            continue;
        }
        cin>>a[i]>>b[i];
        dp[i][0]=dp[i][1]=dp[i][2]=inf;
    }
    dp[0][0]=0;
    for(int i=1;i<=n;i++){
        for(int j=0;j<3;j++){
            for(int k=0;k<3;k++){
                if(a[i-1]+k!=a[i]+j){
                    dp[i][j]=min(dp[i][j],dp[i-1][k]+b[i]*j);
                }
            }
        }
    }
    ll ans=inf;
    for(int i=0;i<3;i++)ans=min(ans,dp[n][i]);
    cout<<ans<<endl;
}

B.

奇偶性相同的数不能交换位置,也就是说奇偶性相同的数的相对位置不变,其他交换无限制
那么我们把奇数和偶数分别放在两个队列里,把较小的数放进答案里即可

queue<char>ji,ou;
void solve() {
    while(ji.size())ji.pop();
    while(ou.size())ou.pop();
    string s;cin>>s;
    for(int i=0;i<s.size();i++){
        if((s[i]-'0')&1)ji.push(s[i]);
        else ou.push(s[i]);
    }
    while(ji.size()&&ou.size()){
        if(ji.front()<ou.front()){
            cout<<ji.front();ji.pop();
        }else if(ji.front()>ou.front()){
            cout<<ou.front();ou.pop();
        }
    }
    while(ji.size()){
        cout<<ji.front();ji.pop();
    }
    while(ou.size()){
        cout<<ou.front();ou.pop();
    }
    cout<<endl;
}

C.

因为点都在街道上,且街道贯穿整个图
若一个点是十字路口,那么任一点到这点都可以是曼哈顿距离
任一点在水平街道上,那么十字路口的垂直街道一定通过这条水平街道;在垂直街道上同理
若一点在水平街道上,一点在垂直街道上,那么它们也可以是曼哈顿距离,理由同上
现在考虑两点都在水平(垂直)街道上
在同一条水平(垂直)街道上一定是曼哈顿距离
考虑不在同一条街道上的

如这张图上的3、4两点,若有一条水平街道在3的高度-4的高度之间,那么它们就可以是曼哈顿距离,没有,则不是
但判两点,过于暴力
去找有贡献的点的共性(找区间,找范围)
转化:
如图的第3个点,比y坐标大的第一条水平线记为l,那么高度处于y坐标与l之间的且同为竖直线上的这些点都与第3点形成贡献

代码有注释:

vector<int>vx,vy;
void solve() {
    int n,m,k;cin>>n>>m>>k;
    for(int i=1,x;i<=n;i++){
        cin>>x;
        vx.push_back(x);//垂直线
    }
    for(int i=1,x;i<=m;i++){
        cin>>x;
        vy.push_back(x);//水平线
    }
    map<int,int>mpx,mpy;
    map<pair<int,int>,int>mp_xy,mp_yx;
    ll ans=0;
    while(k--){
        int x,y;cin>>x>>y;
        int px= lower_bound(vx.begin(),vx.end(),x)-vx.begin();//在哪一条垂直线上
        int py= lower_bound(vy.begin(),vy.end(),y)-vy.begin();//在哪一条水平线上
        if(vx[px]==x&&vy[py]==y)continue;//若该点水平线垂直线都有,也就是十字路口,那么它与任意一点都可以是曼哈顿距离,对答案无贡献,跳过
        if(vx[px]==x){//有垂直线,那么必定无水平线,找到的是比y坐标大的第一条水平线,记为l,mpy[]代表所有无水平线的并且处于y坐标与l之间的点的数量,这些点对答案都有贡献
            ans=ans+mpy[py]-mp_xy[{px,py}];//mp_xy[]表示无水平线且下标为px的垂直线的集合
            mpy[py]++;mp_xy[{px,py}]++;//更新
        }
        else{//同理
            ans=ans+mpx[px]-mp_yx[{py,px}];
            mpx[px]++;mp_yx[{py,px}]++;
        }
    }
    cout<<ans<<endl;
    vx.clear();vy.clear();
}
posted @ 2023-11-13 19:36  WW爆米花  阅读(2)  评论(0编辑  收藏  举报