• 四校联考【20171001】


    T1

    [二分]

    期望得分:70

    实际得分:10

    枚举最高的高度可能为多少+二分。O(logm)

    枚举最高高度应该位于哪一列上.O(n)

    左右扩散枚举出需要用的积木总数,与m相比较。

    容易发现合法的高度的最高值,最终需要搭建一个金字塔。

    1,3,5,7…                        

    正解是预处理出每一列作为最高列的左右边界。

    然后再二分最大高度。

    Check出每个数是否合法即可。

    考场做法的错误在于:并不要堆成完全的金字塔形状。


    例如上图,其实只需要绿色部分就够了。

    居然这么还能苟到10分。。

    但是离正解很近了啊啊啊。

    【code】

    #include<bits/stdc++.h>
    using namespace std; 
    #define ll long long 
    #define File "block"
    inline void file(){
        freopen(File".in","r",stdin);
        freopen(File".out","w",stdout);
    }
    inline int read(){
        int x = 0,f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){if(ch=='-')f = -1; ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = (x<<1) + (x<<3) + ch-'0'; ch = getchar();}
        return x*f;
    }
    const int mxn = 1e5 + 5;
    int n,m;
    int a[mxn];
    int L[mxn],R[mxn];
    int mx;
    ll s[mxn];
    
    inline bool check(int h){
        int l = n,r = 1;
        for(int i = n;i >= 1; --i){
            while(a[l] < h-(i-l) && l >= 1) l--;
            L[i] = l;
        }
        for(int i = 1;i <= n; ++i){
            while(a[r] < h-(r-i) && r <= n) r++;
            R[i] = r;
        }
        
        for(int i = 1;i <= n; ++i){
            ll p,q,t;
            if(L[i] < 1 || R[i] > n) continue; 
            p = h-(i-L[i]),q = h-(R[i]-i);
            t = 1ll*h*h-1ll*(p+1)*p/2-1ll*(q+1)*q/2-(s[R[i]-1]-s[L[i]]);
            if(t <= m) return true;        
        }
        return false;
    }
    
    int main(){
        file();
        n = read(),m = read();
        for(int i = 1;i <= n; ++i) a[i] = read(),mx = max(mx,a[i]),s[i] = s[i-1]+(ll)a[i];
        
        int l = mx+1,r = (int)(sqrt(m)+1)+mx+1;
        while(l < r){
            int mid = (l+r) >>1;
            if(check(mid)) l = mid+1;
            else r = mid;
        }
        printf("%d
    ",l-1);
        return 0;
    }
    /*
    8 4
    3
    4
    2
    1
    3
    3
    2
    4
    */
    /*
    3 100
    3
    3
    3
    */
    View Code

    T2

    [贪心,链表]

    期望得分:30

    实际得分:0

    知道是个贪心。对于每个n[i],贪心选择较大的前n[i]个m[i]减去1。

    正解做法是对贪心进行优化。

    正解的链表做法好玄妙好棒哦。

    能这么做是因为值域就在[1,m]范围内,而且每次变化就在相邻的两个元素之间。

    这样可以用链表快速维护相邻两个数的关系。

    据说还有网络流的写法。不想写。我不会。

     【code】

    #include<bits/stdc++.h>
    using namespace std; 
    #define ll long long 
    #define File "cake"
    inline void file(){
        freopen(File".in","r",stdin);
        freopen(File".out","w",stdout);
    }
    inline int read(){
        int x = 0,f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){if(ch=='-')f = -1; ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = (x<<1) + (x<<3) + ch-'0'; ch = getchar();}
        return x*f;
    }
    const int mxn = 2.5*1e6 + 19;
    int m,n,md,nd,m0,n0;
    inline bool cmp(int x,int y){
        return x > y;
    }
    int X[mxn],Y[mxn];
    int L[mxn],R[mxn];
    
    inline void del(int x){
        L[R[x]] = L[x];
        R[L[x]] = R[x];
    } 
    int main(){
        file();
        m = read(),n = read(),m0 = read(),md = read(),n0 = read(),nd = read();
        X[m0]++,Y[n0]++;    
        for(int i = 1;i < m; ++i)
            m0 = (m0*58+md)%(n+1),X[m0]++;
        for(int i = 1;i < n; ++i)
            n0 = (n0*58+nd)%(m+1),Y[n0]++;
    
        for(int i = 1;i < max(n,m)+9; ++i)        
            L[i] = i+1,R[i] = i-1;//从大到小链接 
        
        int cur = m,s(0);
        ll ans(0);
        for(int i = n; i; --i){
            while(X[i] && cur){
                --X[i];
                while(s < i && R[cur]){
                    s += Y[cur];
                    cur = R[cur];
                }
                while(s >= i+Y[cur]){
                    s -= Y[cur];
                    cur = L[cur];
                }
                ans += (ll)min(i,s);
                if(s > i){
                    int x = Y[cur] - (s-i);
                    if(R[cur]) Y[R[cur]] += x;
                    s -= x;
                    Y[cur] += Y[L[cur]] - x;
                    del(L[cur]);
                }else{
                    s -= Y[cur];
                    if(R[cur]) Y[R[cur]] += Y[cur];
                    del(cur);
                    cur = L[cur];
                } 
            }
        }    
        printf("%d
    ",ans); 
                    
        return 0;
    } 
    /*
    5 8 1 2 3 4
    */
    View Code

    T3

    [树形dp]

    可能的得分:30

    实际得分:0

    暴力就是看图模拟吧。但是没写就是了。

    整体总结:

    状态不佳。。。不给自己找客观原因吧。

  • 相关阅读:
    互联网创业的葵花宝典
    null和undefined的区别
    mpc0.9编译方法
    gmp5.0.5编译
    为iphone及iphone simulator编译poco库
    binutils2.22编译心得
    为iphone及iphone simulator编译qt库
    sql server之触发器调用C#CLR存储过程实现两个表的数据同步
    poco之HttpRequest之get方法
    poco之HttpRequest之post方法
  • 原文地址:https://www.cnblogs.com/ve-2021/p/11342381.html
Copyright © 2020-2023  润新知