• 小w的魔术扑克(牛客CSP-S提高组赛前集训营1 T3)


    传送门

    这是一道好题!

    要求一张牌只能用一面,说明选了一面就不能选另一面(废话)。

    这种限制关系我们可以用二分图的思想解决。

    于是把每张牌的两面的值连边。

    对于一条边只能选一个端点。

    如果连出了环说明每个点都能被选到,如果连出的是树,说明一定有一个点是选不到的。

    我们要求的顺子中如果包含了一棵树,那么这棵树包含的那一段就是凑不出的,即不合法。

    求出一个联通块是环还是树并查集即可。

    对于每一棵树我们可以求出它的max和min。

    那现在问题转化为:对于一段区间,判断它是否完全包含了一些小区间。

    按照右端点排序,看左端点是否包括即可。

    而那些不包括在牌内的值在图中就变成了一个点(可以说是简化的树吧)。

    如果顺子要求这个值肯定也是不合法的。

    #include<bits/stdc++.h>
    #define LL long long
    #define N 100003
    #define INF 2100000000
    #define mod 1000000007
    using namespace std;
    int read()
    {
        int x=0,f=1;char s=getchar();
        while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x*f;
    }
    int n,K,Q; 
    int minn,maxx,fa[N],vis[N],ans[N];
    vector<int>tree[N],q;
    struct node{
        int l,r,id;
    }qry[N];
    vector<node>V;
    bool cmp(const node &x,const node &y)
    {
        return x.r<y.r;
    }
    int get(int x)
    {
        if(fa[x]==x)return x;
        return fa[x]=get(fa[x]);
    }
    void dfs(int x)
    {
        minn=min(minn,x);maxx=max(maxx,x);
        for(int i=0;i<tree[x].size();++i)
        {
            int v=tree[x][i];
            if(vis[v])continue;
            vis[v]=1;
            dfs(v);
        }
    }
    int main()
    {
        n=read();K=read();
        for(int i=1;i<=n;++i)fa[i]=i;
        for(int i=1;i<=K;++i)
        {
            int a=read(),b=read();
            int f1=get(a),f2=get(b);
            if(f1==f2)q.push_back(a);//判断是环是树 
            else
            {
                fa[f1]=f2;
                tree[a].push_back(b);
                tree[b].push_back(a);
            } 
        }
        for(int i=0;i<q.size();++i)
          if(!vis[q[i]])vis[q[i]]=1,dfs(q[i]); 
        for(int i=1;i<=n;++i)
        {
            if(vis[i])continue;
            minn=n,maxx=1;
            vis[i]=1;
            dfs(i);
            V.push_back({minn,maxx,0});
        }
        Q=read();
        for(int i=1;i<=Q;++i)qry[i].l=read(),qry[i].r=read(),qry[i].id=i;
        sort(qry+1,qry+1+Q,cmp);
        sort(V.begin(),V.end(),cmp);
        int p=0,maxl=0;
        for(int i=1;i<=Q;++i)//将所有询问放在一起处理 
        {
            while(p<V.size()&&V[p].r<=qry[i].r)maxl=max(maxl,V[p].l),p++;
            if(maxl>=qry[i].l)ans[qry[i].id]=1;
        }
        for(int i=1;i<=Q;++i)
        {
            if(ans[i])printf("No
    ");
            else printf("Yes
    ");
        }
        return 0;
    } 
    /*
    */
    View Code
  • 相关阅读:
    Python之数据结构:元组
    Python之数据结构:列表
    python学习之路-第一天-接触python
    微信公众号的搭建-第五天-自定义菜单
    微信公众号的搭建-第四天(2)-获取并缓存access_token
    微信公众号的搭建-第四天-完成消息接受和返回响应的消息类型
    微信公众号的搭建-第三天-对请求、事件、响应类的封装
    鸟哥的Linux私房菜-第一部分-第3章主机规划与磁盘分区
    微信公众号的搭建-第二天-申请公众号并与本地测试服务器绑定
    微信公众号的搭建-第一天-搭建一个测试服务器
  • 原文地址:https://www.cnblogs.com/yyys-/p/11779557.html
Copyright © 2020-2023  润新知