zoukankan      html  css  js  c++  java
  • acwing-239-奇偶游戏(离散化+前缀和+带权并查集)+acwing164可达性统计(bitset使用+拓扑排序)

    acwing-239-奇偶游戏(离散化+前缀和+带权并查集)

    题意:

    小A和小B在玩一个游戏。

    首先,小A写了一个由0和1组成的序列S,长度为N。

    然后,小B向小A提出了M个问题。

    在每个问题中,小B指定两个数 l 和 r,小A回答 S[l~r] 中有奇数个1还是偶数个1。

    机智的小B发现小A有可能在撒谎。

    例如,小A曾经回答过 S[1~3] 中有奇数个1, S[4~6] 中有偶数个1,现在又回答 S[1~6] 中有偶数个1,显然这是自相矛盾的。

    请你帮助小B检查这M个答案,并指出在至少多少个回答之后可以确定小A一定在撒谎。

    即求出一个最小的k,使得01序列S满足第1~k个回答,但不满足第1~k+1个回答。

    解:

    1,n的范围在1e9,但是m的范围在1e4,m次输入每次最多两个数,所以数据大概在2e4,需要离散化一下,将不同数据映射进去;

    2,使用前缀和 和 并查集处理问题

    计算l和r范围内1的数有奇数个还是偶数个,即为计算sum【r】-sum[l-1];,具体的题中不用进行计算...

    并查集即为前缀和中每个元素的奇偶性(奇数-奇数=偶数,偶数-偶数=偶数,奇偶性不同时,会出现差值为奇数的情况)

    所有前缀和元素会合并到一个祖先之中,d[x]维护x与根节点奇偶性是否相同

     如果两个元素已经合并在同一个祖先下,那么就可以根据他们与祖先的奇偶性异同,得到他们的异同,判断他们与输入的异同是否一致 如果不一致就是发生矛盾,输出答案...

    %2!=&1

    异或是相同为0,不同为1,奇数末尾&1=0,偶数末尾&1=1;

    奇数%2=1,偶数%2=0...

    代码:

    #include<bits/stdc++.h>
    const int maxn=1e6+10;
    typedef long long ll;
    using namespace std;
    
    ll n;
    int m;
    
    int fa[maxn],d[maxn];
    int cnt=0;
    unordered_map<int ,int> mp;
    
    int get(int x)//离散化
    {
        if(mp.count(x)==0) mp[x]=++cnt;
        return mp[x];
    }
    
    void init()
    {
        for(int i=1; i<=maxn-10; i++) 
         fa[i]=i;
    }
    
    int find(int x)
    {
        if(x!=fa[x])
        {
            int root=find(fa[x]);
            d[x]+=d[fa[x]]%2;//判断奇偶
            fa[x]=root;
        }
        return fa[x];
    }
    
    int main()
    {
        cin>>n>>m;
        int ans=m;
        init();
        for(int i=1; i<=m; i++)
        {
            int x,y;
            string  s;
            cin>>x>>y>>s;
            x=get(x-1),y=get(y);
            int fx=find(x),fy=find(y);
            if(fx==fy)
            {
                if(s=="even")
                {
                    //奇偶性相同
                    if((d[x]+d[y])%2!=0)//奇数,有矛盾
                    {
                        ans=i-1;
                        break;
                    }
                }
                else if(s=="odd")
                {//奇偶性不同
                    if((d[x]+d[y])%2!=1)//偶数,有矛盾
                    {
                        ans=i-1;
                        break;
                    }
                }
            }
            else
            {//合并
                fa[fx]=fy;//0,1区分奇偶
                int add=0;
                if(s=="odd") add=1;
                d[fx]=(d[x]+d[y]+add)%2;
            }
            
        }
        cout<<ans<<endl;
        system("pause");
        return 0;
    }

     acwing164可达性统计(bitset使用+拓扑排序)

    题意:统计一个点能到多少个点,输出

    解:

    首先用拓扑排序对点进行排序,再使用bitset进行位运算压缩,求并集。

    bitset的使用:

    类似于bool,但是它的每个位置只占1bit(特别小)

    bitset的原理大概是将很多数压成一个,从而节省空间和时间

    一般来说bitset会让你的算法复杂度 /32

    定义bitset<maxn> bit;

    bitset支持所有的位运算;

    对于一个叫做bit的bitset:
    bit.size() 返回大小(位数)
    bit.count() 返回1的个数
    bit.any() 返回是否有1
    bit.none() 返回是否没有1
    bit.set() 全都变成1
    bit.set(p) 将第p + 1位变成1(bitset是从第0位开始的!)
    bit.set(p, x) 将第p + 1位变成x
    bit.reset() 全都变成0
    bit.reset(p) 将第p + 1位变成0
    bit.flip() 全都取反
    bit.flip(p) 将第p + 1位取反
    bit.to_ulong() 返回它转换为unsigned long的结果,如果超出范围则报错
    bit.to_ullong() 返回它转换为unsigned long long的结果,如果超出范围则报错
    bit.to_string() 返回它转换为string的结果

    此题用到bit.count(),bit.reset(),当然此题的bit是一个数组;

    代码:

    #include<bits/stdc++.h>
    const int maxn=3e4+10;
    typedef long long ll;
    using namespace std;
    
    vector<int> G[maxn];
    vector<int> Tup;
    bitset<maxn> F[maxn];
    int in[maxn];
    int n, m;
    
    void Tupo()
    {
        queue<int> que;
        for (int i = 1;i <= n;i++)
        {
            if (in[i] == 0)
                que.push(i);
        }
        while (!que.empty())
        {
            int node = que.front();
            que.pop();
            Tup.push_back(node);
            for (int i = 0;i < G[node].size();i++)
            {
                int to = G[node][i];
                if (--in[to] == 0)
                    que.push(to);
            }
        }
    }
    
    
    void Solve()
    {
        for (int i = n-1;i >= 0;i--)
        {
            int x = Tup[i];
            F[x].reset();
            F[x][x] = 1;
            for (int k = 0;k < G[x].size();k++)
            {
                F[x] |= F[G[x][k]];
            }
        }
    }
    
    int main()
    {
        scanf("%d%d", &n, &m);
        int u, v;
        for (int i = 1;i <= m;i++)
        {
            scanf("%d%d", &u, &v);
            G[u].push_back(v);
            in[v]++;
        }
        Tupo();
        Solve();
        for (int i = 1;i <= n;i++)
            printf("%d
    ", (int)F[i].count());
    
        return 0;
    }
  • 相关阅读:
    realmysql 配套书 资料
    韩国 DBA 博客
    Linux Storage Stack Diagram 4.0
    mysql56 在线源码查看
    导致“mysql has gone away”的两种情况
    mysqldump中使用flush tables with read lock的风险分析
    使用Percona Data Recovery Tool for InnoDB恢复数据
    mha-helper ----ovaistariq DBA GITHUB
    MySQL必知必会面试题 基础
    Zabbix-3.0.3使用自带模板监控MySQL
  • 原文地址:https://www.cnblogs.com/sweetlittlebaby/p/13440760.html
Copyright © 2011-2022 走看看