zoukankan      html  css  js  c++  java
  • ABC203

    C

    题意:有从0开始编号的村子0, 1, 2, 3, ..., 一开始taro在0号,有k元,每去一个村子需要花费1元,taro有N个朋友,分别站在N个村子,当taro到第i个朋友站的村子的时候,第i个朋友会给他ki元,问taro能走到的最大编号是多少

    方法:模拟或者二分(一开始想复杂了)

    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    #define int long long
    
    const int N = 2e5 + 10;
    
    int n, k;
    
    struct node{
        int a, b;
        bool operator<(const node &n){
            return a < n.a;
        }
    }a[N];
    
    signed main(){
        cin >> n >> k;
        for(int i = 1; i <= n; i ++) cin >> a[i].a >> a[i].b;
        sort(a + 1, a + 1 + n);
        int res = k, i = 0;
        while(res >= a[i].a){
            res += a[i].b;
            i ++;
            if(i > n) break;
        }
        cout << res;
    }
    

    D

    题意:给你一个NxN网格g,每一个网格上有一个数字,问这个网格中所有大小为KxK的子矩阵中最小能达到的中位数的值是多少

    方法:二分答案,如果存在一个K^2的网格使得中位数小于等于x,那么所有>= x的值均能满足条件,所以满足二段性,一定能找到最小的x,另外就是check函数复杂度的问题,如果直接暴力去找每一个K^2大小的矩阵的中位数再和x比的话是(O((N-K+1)^2K^2)), 肯定T,因为check函数需要判断是否存在一个k^2大小的矩阵使得它的中位数<= x, 所以只需要对每一个k^2大小的矩阵判断他里面> x的数的个数是否满足< k^2 / 2就行了,这里可以用提前标记+前缀和来做,复杂度(O(N^2log1e9))

    #include<iostream>
    using namespace std;
    
    const int N = 810;
    
    int n, k;
    int a[N][N], st[N][N];
    
    int check(int x){
        for(int i = 1; i <= n; i ++)
            for(int j = 1; j <= n; j ++)
                st[i][j] = a[i][j] > x;
        
        for(int i = 1; i <= n; i ++)
            for(int j = 1; j <= n; j ++)
                st[i][j] += st[i - 1][j] + st[i][j - 1] - st[i - 1][j - 1];
        
        for(int i = 1; i <= n - k + 1; i ++)
            for(int j = 1; j <= n - k + 1; j ++){
                int p = i + k - 1, q = j + k - 1;
                int val = st[p][q] - st[i - 1][q] - st[p][j - 1] + st[i - 1][j - 1];
                if(val < k * k / 2 + 1) return 1;
            }
            
        return 0;
    }
    
    int main(){
        cin >> n >> k;
        for(int i = 1; i <= n; i ++)
            for(int j = 1; j <= n; j ++)
                cin >> a[i][j];
        
        int l = 0, r = 1e9;
        while(l < r){
            int mid = l + r >> 1;
            if(check(mid)) r = mid;
            else l = mid + 1;
        }
        
        cout << l << endl;
    }
    

    类似的题:https://codeforces.com/contest/1288/problem/D

    题意:给你n个序列(a_1, a_2, ..., a_n),每一个序列长为m(m <= 8),任选序列ai和aj构成b,令bk = max(aik, ajk),问能够构成的序列b中最小值最大为多少

    方法:二分答案,注意如果再check函数里面直接枚举i和j然后求b看是否能够找到这样的b它的最小值>= x,复杂度(O(N^2))过不了,方法是对于ai计算一个数字t,如果ai是5,4,3,2,1,而x = 3,那么ai所得到的数字是(t=(11100)_2),就是只要是aik满足>= x就令t的从高向低的第k位为1,因为m很小,所以对于所有的ai,计算得到的数字数不超过2m,将所有得到的数字存起来,然后枚举其中的任意两个数,如果满足两者相或为2m - 1,那么就说明通过这两个序列得到的序列b满足最小值>= x,直接返回1即可

    #include<iostream>
    #include<algorithm>
    #include<map>
    
    using namespace std;
    
    const int N = 3e5 + 10;
    
    int a[N][10];
    
    int n, m;
    pair<int, int> ans{1, 1};
    
    int check(int x){
        map<int, int> mp;
        for(int i = 1; i <= n; i ++){
            int t = 0;
            for(int j = 1; j <= m; j ++)
                t = t * 2 + (a[i][j] >= x);
            mp[t] = i;
        }
    
        for(auto i : mp)
            for(auto j : mp)
                if((i.first | j.first) == (1 << m) - 1){
                    ans = {i.second, j.second};
                    return 1;
                }
                     
        return 0;
    }
    
    int main(){
        cin >> n >> m;
        for(int i = 1; i <= n; i ++)
            for(int j = 1; j <= m; j ++)
                cin >> a[i][j];
        
        int l = 0, r = 1e9;
        while(l < r){
            int mid = l + r + 1 >> 1;
            if(check(mid)) l = mid;
            else r = mid - 1;
        }
        
        cout << ans.first << ' ' << ans.second << endl;
    }
    
  • 相关阅读:
    python re模块
    python
    python
    Django学习手册
    Django学习手册
    前端
    前端
    Django学习手册
    前端
    Database学习
  • 原文地址:https://www.cnblogs.com/tomori/p/15505973.html
Copyright © 2011-2022 走看看