zoukankan      html  css  js  c++  java
  • Codeforces 1288D 状态压缩+二分

    状态压缩好猛啊

    题意

      给了n个数组,每个输出的长度为m(n<3e5,m<8)。让你选择两个数组a,b。定义数组c,ci=max(ai,bi)。

    让c数组的最小值最大。输出两个数组a,b的下标即可。

    思路

      很明显二分答案1e9。然后问题演变成对于答案x,这n个数组满不满足存在两个数组产生的c数组在每一个位置都大于x。

      技巧:进行状态压缩。对于答案x,遍历每个数组,该数组的第i位大于等于x,则该位置二进制为1,否则为0。

    于是n个长度为m的数组演变成n个长度为m的二进制形式,再转化成int整形。因为m最大为8,所以最大不超过28(255)。

    暴力哪些数进行或操作等于2m且存在n个数当中即可。

    #include <iostream>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <map>
    #include <iomanip>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <set>
    #include <vector> 
    // #include <bits/stdc++.h>
    #define fastio ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    #define sp ' '
    #define endl '
    '
    #define inf  0x3f3f3f3f;
    #define FOR(i,a,b) for( int i = a;i <= b;++i)
    #define bug cout<<"--------------"<<endl
    #define P pair<int, int>
    #define fi first
    #define se second
    #define pb(x) push_back(x)
    #define ppb() pop_back()
    #define mp(a,b) make_pair(a,b)
    #define ms(v,x) memset(v,x,sizeof(v))
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define repd(i,a,b) for(int i=a;i>=b;i--)
    #define sca3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
    #define sca2(a,b) scanf("%d %d",&(a),&(b))
    #define sca(a) scanf("%d",&(a));
    #define sca3ll(a,b,c) scanf("%lld %lld %lld",&(a),&(b),&(c))
    #define sca2ll(a,b) scanf("%lld %lld",&(a),&(b))
    #define scall(a) scanf("%lld",&(a));
    
    
    using namespace std;
    typedef long long ll;
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
    ll powmod(ll a, ll b, ll mod){ll sum = 1;while (b) {if (b & 1) {sum = (sum * a) % mod;b--;}b /= 2;a = a * a % mod;}return sum;}
    
    const double Pi = acos(-1.0);
    const double epsilon = Pi/180.0;
    const int maxn = 3e5+10;
    int n,m;
    int a[maxn][10];
    int b[maxn][10];
    int vis[300];
    int ans1,ans2;
    int pos;
    void Init()
    {
        cin>>n>>m;
        rep(i,1,n){
            rep(j,1,m){
                cin>>a[i][j];
            }
        }
    }
    int OK(int x)
    {
        memset(vis,0,sizeof(vis));
        rep(i,1,n){
            int t = 0;
            rep(j,1,m){
                if(a[i][j]>=x){
                    t = t*2+1;
                }else t *= 2;
            }
            vis[t] = i;
        }
        int maxx = 0;
        rep(i,1,m){
            maxx = maxx*2+1;
        }
        rep(i,0,maxx){
            rep(j,0,maxx){
                if(vis[i]&&vis[j]&&(i|j)==maxx){
                    ans1 = vis[i];
                    ans2 = vis[j];
                    //pos = x;
                    return 1;
                }
            }
        }
        return 0;
    
    }
    int main()
    {
        Init();
        int l = 0,r = 1e9;
        while(l <= r){
            int mid = (l+r)/2;
            if(OK(mid)){
                l = mid+1;
            }else{
                r = mid-1;
            }
        }
       // cout<<pos<<endl;
        cout<<ans1<<sp<<ans2<<endl;
    
    }
  • 相关阅读:
    Java实现 蓝桥杯 算法提高 小X的购物计划
    Java实现 蓝桥杯 算法提高 小X的购物计划
    Java实现 第十一届 蓝桥杯 (高职专科组)省内模拟赛
    Java实现 第十一届 蓝桥杯 (高职专科组)省内模拟赛
    Java实现 第十一届 蓝桥杯 (高职专科组)省内模拟赛
    Java 第十一届 蓝桥杯 省模拟赛 小明的城堡
    Java 第十一届 蓝桥杯 省模拟赛 小明的城堡
    Java 第十一届 蓝桥杯 省模拟赛 小明的城堡
    129. Sum Root to Leaf Numbers
    117. Populating Next Right Pointers in Each Node II
  • 原文地址:https://www.cnblogs.com/jrfr/p/13373816.html
Copyright © 2011-2022 走看看