zoukankan      html  css  js  c++  java
  • 2020杭电多校(一) Finding a MEX(分块)

    比赛的时候根据数据范围马上猜出了是通过轻重点分块,但是在维护set的时候犯了一个nt错误

    选择了插入邻边的权值去判断第一个未出现的答案,怎么想都觉得复杂度很高。

    其实可以选择先插入所有得可能答案,然后对邻边影响得答案进行删除,这样set中得第一个元素就是答案。

    这题复杂度保证得原因是,通过分块,对于边数大于1000的称为重点,去维护一个set,因为边总共只有1e5条,这样的点不会超过100个,并且只需要维护从0-度数这样长度的set就行

    后面的值肯定不会影响答案。

    对于轻点,只需要暴力枚举所有的边去暴力判断,因为轻点邻边不会超过1000条,所以复杂度也得到保证

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e5+10;
    const int mod=998244353;
    vector<int> g[N];
    set<int> s[N];
    int in[N];
    int num[110][N];
    int id[N];
    bool st[N];
    int a[N];
    vector<int> now[N];
    int main(){
        ios::sync_with_stdio(false);
        int i;
        int t;
        cin>>t;
        while(t--){
            int n,m;
            cin>>n>>m;
            int i;
            for(i=1;i<=n;i++)
                cin>>a[i];
            for(i=1;i<=n;i++){
                g[i].clear();
                in[i]=0;
                now[i].clear();
            }
            int block=1000;
            for(i=1;i<=m;i++){
                int x,y;
                cin>>x>>y;
                g[x].push_back(y);
                g[y].push_back(x);
                in[x]++,in[y]++;
            }
            int cnt=0;
            for(i=1;i<=n;i++){
                if(in[i]>=block){
                    id[i]=++cnt;//ÀëÉ¢»¯Ó³Éä
                    int j;
                    s[cnt].clear();
                    for(j=0;j<=in[i];j++){
                        s[cnt].insert(j),num[cnt][j]=0;
                    }
                }
            }
            for(i=1;i<=n;i++){
                int j;
                for(j=0;j<g[i].size();j++){
                    int u=g[i][j];
                    if(in[u]>=block){
                        if(a[i]<=in[u]){
                            if(++num[id[u]][a[i]]==1){
                                s[id[u]].erase(a[i]);
                            }
                            now[i].push_back(u);
                        }
                    }
                }
            }
            int q;
            cin>>q;
            while(q--){
                int opt;
                cin>>opt;
                if(opt==1){
                    int x,y;
                    cin>>x>>y;
                    for(auto tmp:now[x]){
                        if(y<=in[tmp]){
                            if(++num[id[tmp]][y]==1)
                                s[id[tmp]].erase(y);
                        }
                        if(a[x]<=in[tmp]){
                            if(--num[id[tmp]][a[x]]==0){
                                s[id[tmp]].insert(a[x]);
                            }
                        }
                    }
                    a[x]=y;
                }
                else{
                    int x;
                    cin>>x;
                    if(in[x]>=block){
                        cout<<*s[id[x]].begin()<<endl;
                    }
                    else{
                        for(i=0;i<g[x].size();i++){
                            int v=g[x][i];
                            if(a[v]<=in[x]){
                                st[a[v]]=1;
                            }
                        }
                        int ans=0;
                        while(st[ans])
                            ans++;
                        cout<<ans<<endl;
                        for(i=0;i<g[x].size();i++){
                            int v=g[x][i];
                            if(a[v]<=in[x]){
                                st[a[v]]=0;
                            }
                        }
                    }
                }
            }
        }
        return 0;
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    Centos7 安装RabbitMQ 3.6.1
    面向对象编程(类的绑定方法与非绑定方法)
    面向对象编程(封装、封装的意义、封装与扩展性、@property)
    函数式编程(__slots__)
    面向对象编程(实例属性、类属性)
    面向对象编程(获取对象信息)
    面向对象编程(继承、多态)
    函数式编程(访问限制)
    面向对象编程(类与实例)
    面向对象编程(基础简介)
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13363529.html
Copyright © 2011-2022 走看看