• *Finding a MEX【轻重点分块】-2020杭电多校1


    题意:

    给出一个图,(n) 个点 (m) 条边,每个点有一个权值 (A_i),定义 (F(u))(mex{A_v|(u,v)in E })。有两种操作:
    1.将 (A_u) 的值改为 (x)
    2.求出 (F(u)) 的值;

    分析:

    首先要明确点 (F(u)) 的值一定不会超过点 (u) 的度。选定一个值为度的界限,当点的度超过该值时,视为重点,否则为轻点。对于重点,由于其相连的点的个数比较多,所以用一个 (set) 维护,保证 (set) 的第一个数就是答案;对于轻点,由于相连的点比较少,可以采用直接暴力的方式。通过这种方法,可以降低复杂度。
    注意要记录每个数的出现的次数,界限的选取和边的数量有关,此处选 (1000)

    代码:

    #include <bits/stdc++.h>
    #define pb push_back
    using namespace std;
    const int N=1e5+5;
    int a[N],degree[N];//点权和每个点的度
    vector<int>pic[N];
    int block=1000;
    set<int>st[N];
    int vis[1010],num[110][N],id[N];//只存重点周围的权值出现的次数
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int n,m,u,v,x,q,op;
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++)
            {
                pic[i].clear();
                degree[i]=0;
                id[i]=0;
            }
            for(int i=1;i<=n;i++)
                scanf("%d",&a[i]);
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d",&u,&v);
                pic[u].pb(v);
                pic[v].pb(u);
                degree[u]++,degree[v]++;//记下每个点的度
            }
            //要记录权值出现的次数
            int cnt=0;
            for(int i=1;i<=n;i++)
            {
                if(degree[i]>=block)//重点
                {
                    id[i]=++cnt;//记该点是第几个重点
                    st[cnt].clear();//保证第一个元素为答案
                    for(int j=0;j<=degree[i];j++)
                    {
                        st[cnt].insert(j);
                        num[cnt][j]=0;
                    }
                    for(int j=0;j<pic[i].size();j++)
                    {
                        int t=pic[i][j];
                        if(a[t]<=degree[i])//答案不会超过degree[i]
                        {
                            num[cnt][a[t]]++;
                            st[cnt].erase(a[t]);
                        }
                    }
                }
            }
            scanf("%d",&q);
            while(q--)
            {
                scanf("%d",&op);
                if(op==1)
                {
                    scanf("%d%d",&u,&x);
                    for(int i=0;i<pic[u].size();i++)
                    {
                        int t=pic[u][i];
                        if(id[t]==0) continue;//不对轻点进行处理
                        if(degree[t]>=block)
                        {
                            if(x<=degree[t])
                            {
                                num[id[t]][x]++;
                                st[id[t]].erase(x);
                            }
                            if(a[u]<=degree[t])
                            {
                                num[id[t]][a[u]]--;
                                if(num[id[t]][a[u]]==0)
                                    st[id[t]].insert(a[u]);
                            }
                        }
                    }
                    a[u]=x;
                }
                else
                {
                    scanf("%d",&u);
                    int ans=0;
                    if(degree[u]<block)//轻点,暴力寻找
                    {
                        for(int i=0;i<pic[u].size();i++)
                        {
                            int t=pic[u][i];
                            if(a[t]<=degree[u])
                                vis[a[t]]=1;
                        }
                        for(int i=0;i<=degree[u];i++)
                        {
                            if(!vis[i])
                            {
                                ans=i;
                                break;
                            }
                        }
                        for(int i=0;i<pic[u].size();i++)
                        {
                            int t=pic[u][i];
                            if(a[t]<=degree[u])
                                vis[a[t]]=0;
                        }
                    }
                    else
                        ans=*st[id[u]].begin();
                    printf("%d
    ",ans);
                }
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    SQL中的字符串字段根据某字段实现自增
    SQL中的字符串字段实现自增
    ECS Windows服务器IIS FTP登陆提示“530 valid hostname is expected”
    HTML中动态生成内容的事件绑定问题
    JavaScript对JSON数据进行排序和搜索
    IIS站点下多应用程序 C#获取根目录方法
    asp.net中form表单多个按钮submit提交到后台的实例
    C#从一个SqlCommand对象生成可执行的SQL语句
    传递参数
    js创建jsonArray传输至后台及后台解析
  • 原文地址:https://www.cnblogs.com/1024-xzx/p/13399716.html
Copyright © 2020-2023  润新知