AtCoder Beginner Contest 434 C-E 题解

C. Flapping Takahashi

题意

初始高度为 H H H,可以上下移动,要求每秒高度变化不超过 1 1 1,且高度不能为负。给定 n n n 个限制,第 i i i 个限制为在第 t i t_i ti 秒,高度必须在 l i , u i l_i,u_i li,ui 之间。问是否存在一种可行方案。

思路

对于每个限制,若上次的高度区间已经固定,就可以确定这次能否到达。若上次的时间为 p r v prv prv,区间为 l , r l,r l,r,则这次区间为 l − ( t i − p r v ) , r + ( t i − p r v ) l-(t_i-prv),r+(t_i-prv) l−(ti−prv),r+(ti−prv),判断该区间与 l i , u i l_i,u_i li,ui 是否有交集,并更新 l , r l,r l,r,使 l ← max ⁡ ( l , l i ) l\gets \max(l,l_i) l←max(l,li), r ← min ⁡ ( r , u i ) r\gets \min(r,u_i) r←min(r,ui) 即可。

现在只要知道初始的高度区间即可,显然为 H , H H,H H,H,即 l = r = H l=r=H l=r=H。

时间复杂度 O ( n ) \mathcal{O}(n) O(n)。

C++ 代码

cpp 复制代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
void solve(){
    int n,h; cin>>n>>h;
    int L=h,R=h,prv=0;
    bool fl=1;
    for(int i=1;i<=n;i++){
        int t,l,r; cin>>t>>l>>r;
        L-=(t-prv);
        R+=(t-prv);
        fl&=((R>=l&&r>=L));
        L=max(L,l);
        R=min(R,r);
        prv=t;
    }
    if(fl) cout<<"Yes\n";
    else cout<<"No\n";
}
main(){int T;cin>>T;while(T--)solve();}

D. Clouds

题意

有一个 2000 × 2000 2000\times 2000 2000×2000 的平面,有 n n n 个矩形,对于所有 1 ≤ i ≤ n 1\le i\le n 1≤i≤n,求:不被【除矩形 i i i 以外的任何矩形】覆盖的点有多少个。

思路

这题应该可以扫描线做,但是大可不必。

首先计算不去除任何矩形不覆盖的点的个数 a n s ans ans。然后考虑去除矩形 i i i 的贡献。我们发现,去除矩形 i i i 会增加不覆盖的点个数,当且仅当这个点仅被这一个矩形覆盖。所以我们可以对矩形覆盖位置做一个二维差分,记录那些位置只被覆盖一次,然后覆盖这个位置的矩形的贡献就加一。最后对于每个矩形的贡献 r e s i res_i resi,答案即为 a n s + r e s i ans+res_i ans+resi。

C++ 代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=2005;
int a[N][N],cnt[N][N],cf[N][N],res[200005];
main(){
    int n; cin>>n;
    for(int i=1;i<=n;i++){
        int u,d,l,r; cin>>u>>d>>l>>r;
        cnt[u][l]++; cnt[u][r+1]--; cnt[d+1][r+1]++; cnt[d+1][l]--;
        cf[u][l]+=i; cf[u][r+1]-=i; cf[d+1][r+1]+=i; cf[d+1][l]-=i; //差分记录覆盖它的id,若仅被覆盖一次,此值必为覆盖它的矩形编号
    }
    int ans=0;
    for(int i=1;i<=2000;i++){
        for(int j=1;j<=2000;j++){
            cnt[i][j]+=cnt[i-1][j]+cnt[i][j-1]-cnt[i-1][j-1];
            cf[i][j]+=cf[i-1][j]+cf[i][j-1]-cf[i-1][j-1];
            ans+=(cnt[i][j]==0);
            if(cnt[i][j]==1) res[cf[i][j]]++;
        }
    }
    for(int i=1;i<=n;i++) cout<<ans+res[i]<<endl;
    return 0;
}

E. Distribute Bunnies

题意

数轴上有 n n n 只兔子,第 i i i 只兔子要么站在 X i + R i X_i+R_i Xi+Ri,要么站在 X i − R i X_i-R_i Xi−Ri。问 n n n 只兔子位置的集合去重后的大小最大为多少?

思路

建图。把 X i − R i X_i-R_i Xi−Ri 和 X i + R i X_i+R_i Xi+Ri 连边(注意要把点离散化),问题转化为对于每条边,把其中一个端点涂黑,最多能涂黑多少个点。

考虑每个连通块,若大小为 s z sz sz。

  • 若该连通块为一棵树,显然可以任意一点为根,每条边都涂黑深度较大的那个点,最终只剩下根节点,所以可以涂黑 s z − 1 sz-1 sz−1 个点。
  • 若该连通块为一棵基环树,可以以环为根,每条边都涂黑深度较大的那个点,最终只剩下环上的点,显然环上的点可以都涂黑。所以可以涂黑 s z sz sz 个点。
  • 若该连通块为一个无特殊性质的连通图,可以找到任意一棵生成树,再加一条边变为基环树,转化为上述情形,可以涂黑 s z sz sz 个点。

最终结论,不能涂黑的点数即为树的个数,答案即为总点数减去树的个数。

时间复杂度 O ( n log ⁡ n ) \mathcal{O}(n\log n) O(nlogn),瓶颈在离散化。

C++ 代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n;
map<int,int> mp;
vector<int> g[N<<1];
bool used[N<<1];
int vcnt=0,edgecnt=0;
void dfs(int u){
    used[u]=1;
    vcnt++;
    for(int v:g[u]){
        edgecnt++;
        if(!used[v]){
            dfs(v);
        }
    }
}
int32_t main(){
    int n; cin>>n;
    int cnt=0;//总点数
    for(int i=1;i<=n;i++){
        int x,r; cin>>x>>r;
        int a=x-r,b=x+r;
        if(!mp[a]) mp[a]=++cnt;
        if(!mp[b]) mp[b]=++cnt;
        g[mp[a]].push_back(mp[b]);
        g[mp[b]].push_back(mp[a]);
    }
    int ans=cnt;
    for(int i=1;i<=cnt;i++){
        if(!used[i]){
            vcnt=edgecnt=0;
            dfs(i);
            ans-=(edgecnt/2==vcnt-1);//edgecnt/2 为实际边数,若边数==点数-1,该图为一棵树
        }
    }
    cout<<ans<<endl;
    return 0;
}
相关推荐
别动我齐刘海2 小时前
Linux 系统调试学习1
linux·运维·服务器·c++·学习·机器学习·机器人
Nil2085 小时前
leetcode 198打家劫舍
算法·leetcode·职场和发展
Shaoshing5 小时前
前缀和与差分
java·数据结构·算法·前缀和·差分
loulanyue_6 小时前
构建房产认知决策智能:Harness底座与AI自进化的技术实践——读贝壳首席算法科学家尹俊希2026云栖专场演讲
人工智能·算法
碧海银沙音频科技研究院6 小时前
基于炬芯ATS录音卡BLE控制协议
人工智能·嵌入式硬件·算法·语音识别
jimy16 小时前
C++ 虚函数表:基类和派生类共用一张 vtable 吗?
开发语言·c++
爱吃提升6 小时前
Dev-C++ 5.11 C++断点调试完整教程
开发语言·c++
suhan6 小时前
【数据结构】三、栈和队列:6.链队列、双端队列、队列的应用(树的层次遍历、广度优先BFS、先来先服务FCFS)
数据结构·后端·算法
姜鱼问生7 小时前
Docker Volume 备份与恢复实战:不停机迁移数据
后端·算法·架构
suhan7 小时前
【数据结构】三、栈和队列:5.顺序队列(循环队列)(初始化,判空判满,入队,出队,实例)
数据结构·后端·算法