小L的空投

链接

这道题很容易想到要用并查集,我们只需要用逆向思维

但是,由于数据很大,对于cnt(需要的空投数)不能每次都计数,而是需要实时更新

我们不妨思考,当两个城市合并时,如果二者的根节点不同,那么我们就检查这两个城市的连通块数量,如果大于等于d,cnt就减一,合并完再加上即可

#include<bits/stdc++.h>
using namespace std;
#define ll long long
vector<ll>tree;
int n,m,x,d;
int cnt=0;
struct node{
    ll h;
    int idx;
    bool operator<(const node& other) const{
        return h>other.h;
    }
};
int Find(int x);
void Union(int x,int y);


void solve(){
    cin>>n>>m>>x>>d;
    tree.resize(n,-1);
    vector<node>road(n);
    for(int i=0;i<n;i++){
        cin>>road[i].h;
        road[i].idx=i;
    }
    sort(road.begin(),road.end());
    unordered_map<int,vector<int>>mp;
    for(int i=0;i<m;i++){
        int a,b;
        cin>>a>>b;
        mp[a-1].push_back(b-1);
        mp[b-1].push_back(a-1);
    }
    vector<ll>H(x);
    for(int i=0;i<x;i++){
        cin>>H[i];
    }
    vector<int>ans(x);
    int index=0;
    vector<bool>des(n,0);
    for(int i=x-1;i>=0;i--){
        int it=upper_bound(road.begin(),road.end(),H[i],[](ll val,node x){
            return val>=x.h;
        })-road.begin();
        for(int j=index;j<it;j++){
            des[road[j].idx]=1;
            if(d==1) cnt++;
        }
        for(int j=index;j<it;j++){
            int idx=road[j].idx;
            for(int other:mp[idx]){
                if(des[other]){ 
                    Union(idx,other);
                }
            }
        }
        index=it;
        ans[i]=cnt;
//         for(int i=0;i<n;i++){
//             cout<<tree[i]<<" ";
//         }
//         cout<<'\n';
    }
    for(int num:ans) cout<<num<<'\n';
}


int Find(int x){
    if(tree[x]<0) return x;
    else return tree[x]=Find(tree[x]);
}
void Union(int x,int y){
    int root_x=Find(x);
    int root_y=Find(y);
    if(root_x==root_y) return;
    if(-tree[root_x]>=d) cnt--;
    if(-tree[root_y]>=d) cnt--;
    
        if(root_x<root_y){
            tree[root_x]+=tree[root_y];
            tree[root_y]=root_x;
            if(-tree[root_x]>=d) cnt++;
        }
        else{
            tree[root_y]+=tree[root_x];
            tree[root_x]=root_y;
            if(-tree[root_y]>=d) cnt++;
        }
    
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    solve();
}

题目限制3s,而这个代码能控制在900ms,很好!

全部评论

相关推荐

02-10 14:41
已编辑
门头沟学院 人工智能
事实上,人的创造力和灵光乍现都是在无聊的时候出现,就是因为没事可干才让世界变得这样精彩绝伦,天啊,有太多可玩,可想,有太多值得尝试的内容啦,光是我泱泱华夏都有这么多地方可以去:你可以春天前往西南地带看看春暖花开,你可以夏天去海南享受日光浴,又或者秋天去往新疆体验异域风情,更何况可以冬天上东北看看真正的严寒是什么样的。或者说你喜欢游戏,农药,lol,cs,星露谷,女神异闻录,怪物猎人,黑猴,街霸,我数不清啦,还可以去电竞比赛看看,或者三五好友成群痛痛快快的打游戏,真的,天底下有太多好玩的了,我还没讲完呢,走出门能干什么,想要好的身材可以健身,游泳,滑雪,徒步,露营,玩滑板,想要好的才学可以弹琴,学吉他,去图书馆,去电影院,去音乐会,去漫展,去博物馆,甚至可以养一些动物,猫猫狗狗,有那么多品种,我甚至想养狐獴和白貂,你也可以,去办证书就行了,甚至可以养一些猫头鹰之类的,又或者遇到一个喜欢的漂亮妹妹或者薄肌小帅,与她/他轰轰烈烈的谈一场恋爱,你可能说,我以前遇人不淑,是的,我也这样,这很糟糕,对吧,但是没什么的,你的过往组成了今日的你,你会遇到更好的人的,你会去更大的地方的,我只是一个教学博主,我只能讲一部分内容,这些文字承载着力量,它们涵盖着我想说的,去好好享受此生吧,去享受每一分钟,去往曾经只敢想象的地方,你们需要保持好奇心,我只能告诉你们海的那边是什么样子的,或者山的那头是什么样子的,但是要坐船,还是做飞机过去,这个是由你定的,大胆前行吧,忘却过去那些不愉快的,去做那勇敢而热烈之人,去追求你的快乐吧,最后:欢迎来到,地球online!
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务