zoukankan      html  css  js  c++  java
  • 小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
  • 相关阅读:
    网页挂马实验
    基于内核网络过滤实验
    基与内核的键盘记录实验
    网络蠕虫病毒代码分析
    脚本病毒编写实验
    病毒查找与清除实验
    木马分析(植入分析)实验
    木马分析(控制分析)实验
    木马分析(隐藏分析)实验
    移动存储型病毒分析实验
  • 原文地址:https://www.cnblogs.com/yyys-/p/11779557.html
Copyright © 2011-2022 走看看