zoukankan      html  css  js  c++  java
  • Codeforces Round #637 (Div. 2) A~D

    Codeforces Round #637 (Div. 2) A~D

    http://codeforces.com/contest/1341/

    A. Nastya and Rice

    题意

    (n) 个范围在 ([a-b,a+b]) 的数字,询问他们的和能否在区间 ([c-d,c+d]) 内。

    解题

    (n) 个数字和的范围是 ([n(a-b),n(a+b)]) ,判断是否与 ([c-d,c+d]) 存在交集即可。

    def scanf():
        return list(map(int,input().split()))
    
    for t in range(int(input())):
        n,a,b,c,d = scanf()
        p = n*(a-b); q = n*(a+b)
        if(p>c+d or q<c-d):	print("NO")
        else:	print("YES")
    

    B. Nastya and Door

    题意

    给定一个正整数序列,代表连绵的山脉。序列中如果存在 (a_{i-1}<a_i land a_i>a_{i+1}) 的位置,则称 (a_i) 为山峰。

    有一个巨大的门,把这个门水平扔山上问最多能分成几份。这个门或门的碎片,遇到山峰之后就会分成两半。

    解题

    这个题是真的难翻译,又长又玄幻,不过题目还算简单。

    差分,记录位置前面的山峰数量,寻找山峰最多的区间,在这里把门扔下去分成的份数最多,为山峰数(+1)

    注意下边界的判定,题目中说区间边界的山峰不会分割门。

    #include<bits/stdc++.h>
    #define ll long long
    
    #define fr(i,n) for(int i=0;i<n;i++)
    #define frs(i,n,flag)   for(int i=0;i<n&&flag;i++)
    
    #define frr(i,j,n) for(int i=j;i<n;i++)
    #define r_frr(i,j,n) for(int i=n-1;i>=j;i--)
    
    #define frrs(i,j,n,flag)    for(int i=j;i<n&&flag;i++)
    #define r_frrs(i,j,n,flag)    for(int i=n-1;i>=j&&flag;i--)
    
    #define arend(i,n) ((i!=n-1)?" ":"
    ")
    #define memset0(dp) memset(dp,0,sizeof(dp))
    #define print_arr(begin,end)    for(auto it = begin;it!=end;it++)  cout<<*it<<arend(it,end);
    #define log_this(name,value)    cout<<name<<": "<<value<<endl;
    #define e4 10004
    #define e5 100005
    #define e6 1000006
    #define e7 10000007
    #define e9 1000000000
    #define INF 9999999
    using namespace std;
    int     to_int(string s)    {stringstream ss;ss<<s;int a;ss>>a;return a;}
    string  to_str(double a)    {stringstream ss;ss<<a;return ss.str();}
    
    int a[2*e5];
    int ct[2*e5];	//记录区间 (0,i) 的山峰数量,注意是开区间
    
    int main(){
    
        cin.tie(0);
        //ios::sync_with_stdio(false);
        //cout<<setiosflags(ios::fixed)<<setprecision(0);
    
        //freopen("1.out","w",stdout);
    
        int t;
        while(cin>>t){
            while(t--){
                int n,k;cin>>n>>k;
                fr(i,n) cin>>a[i];
                ct[0] = 0;
                ct[1] = 0;
                frr(i,1,n-1){
                    ct[i+1] = ct[i];
                    if(a[i]>a[i-1]&&a[i]>a[i+1]){
                        ct[i+1]++;
                    }
                }
                ct[n] = ct[n-1];
                int ans = -1;
                int l = 0;
                frr(i,0,n-k+1){
                    if(ans<ct[i+k-1]-ct[i+1]){
                        l = i;
                        ans = ct[i+k-1] - ct[i+1];
                    }
                }
                cout<<ans+1<<" "<<l+1<<endl;
            }
        }
        return 0;
    }
    

    C. Nastya and Strange Generator

    题意

    有一个随机的数字生成器,按照如下生成规则。

    • (i) 次操作将数字 (i) 按照下面规则填入;

    • (r_j) 表示位置 (j) 之后的第一个为空的位置;

    • (count_t) 表示位置 (t) 被其他位置选做 (r_j) 的次数,即 (r.count(t))

    • 每次只能选取 (count_t) 最大的位置填入 (i)

    • 如果有多个相同的最大值,则可以从中选取任意一个。

    给定一个由 (n) 个不同数字组成的数组,询问能否使用该生成器生成。

    解题

    这个题也是题面不是很友好,读题面和理解题意用了很长时间。在50分钟的时候过题没想到还能排到1900,说明很多人都被这题面卡住了(绝了

    通过举例模拟填充过程发现,填充机制很简单。一旦选取位置 (t) 填充数字 (i) ,那么位置 (t+1) 一定是序列中 (count) 值最大的,所以我们的 (i+1) 必须填充到位置 (t+1) 上,以此类推,直至位置被已被填充或者到达末尾。最后得到的填充序列一定满足以下两个条件:

    • 由每小段连续递增子序列组成;
    • 前面的连续递增子序列的元素一定大于后面连续子序列的元素。

    判断输入序列是否同时满足上面两个条件即可。

    #include<bits/stdc++.h>
    #define ll long long
     
    #define fr(i,n) for(int i=0;i<n;i++)
    #define frs(i,n,flag)   for(int i=0;i<n&&flag;i++)
     
    #define frr(i,j,n) for(int i=j;i<n;i++)
    #define r_frr(i,j,n) for(int i=n-1;i>=j;i--)
     
    #define frrs(i,j,n,flag)    for(int i=j;i<n&&flag;i++)
    #define r_frrs(i,j,n,flag)    for(int i=n-1;i>=j&&flag;i--)
     
    #define arend(i,n) ((i!=n-1)?" ":"
    ")
    #define memset0(dp) memset(dp,0,sizeof(dp))
    #define print_arr(begin,end)    for(auto it = begin;it!=end;it++)  cout<<*it<<arend(it,end);
    #define log_this(name,value)    cout<<name<<": "<<value<<endl;
    #define e4 10004
    #define e5 100005
    #define e6 1000006
    #define e7 10000007
    #define e9 1000000000
    #define INF 9999999
    using namespace std;
    int     to_int(string s)    {stringstream ss;ss<<s;int a;ss>>a;return a;}
    string  to_str(double a)    {stringstream ss;ss<<a;return ss.str();}
     
    int a[1*e5];
     
    int main(){
     
        cin.tie(0);
        //ios::sync_with_stdio(false);
        //cout<<setiosflags(ios::fixed)<<setprecision(0);
     
        //freopen("1.out","w",stdout);
     
        int t;
        while(cin>>t){
            while(t--){
                int n;cin>>n;
                fr(i,n) cin>>a[i];
                int lastw = -1;
                int noww = a[n-1];
                bool can = true;
                r_frr(i,1,n){
                    if(a[i-1]>a[i]){
                        if(a[i]<lastw){
                            can = false;
                            break;
                        }
                        lastw = noww;
                        noww = a[i-1];
                    }else{
                        if(a[i]-a[i-1]>1){
                            can = false;
                            break;
                        }
                    }
                }
                if(can) cout<<"YES"<<endl;
                else    cout<<"NO"<<endl;
            }
        }
        
        return 0;
    }
    

    D. Nastya and Scoreboard

    题意

    有一个由火柴棍拼图组成的序列,询问加上 (k) 根火柴棍能够拼出的最大数字是多少。

    解题

    首先题面中有两个事情需要注意:

    • 输入拼图序列中存在非数字的情况;
    • (k) 个火柴可能不能够刚好让所有的拼图变成数字。

    贪心+dfs,从大到小搜索可行情况,注意这里要用记搜,不然会超时。

    既然记搜可过,看这个数据范围,估计也有dp的解法,等有时间再补上(挖坑+1

    #include<bits/stdc++.h>
    #define ll long long
    
    #define fr(i,n) for(int i=0;i<n;i++)
    #define frs(i,n,flag)   for(int i=0;i<n&&flag;i++)
    
    #define frr(i,j,n) for(int i=j;i<n;i++)
    #define r_frr(i,j,n) for(int i=n-1;i>=j;i--)
    
    #define frrs(i,j,n,flag)    for(int i=j;i<n&&flag;i++)
    #define r_frrs(i,j,n,flag)    for(int i=n-1;i>=j&&flag;i--)
    
    #define arend(i,n) ((i!=n-1)?" ":"
    ")
    #define memset0(dp) memset(dp,0,sizeof(dp))
    #define print_arr(begin,end)    for(auto it = begin;it!=end;it++)  cout<<*it<<arend(it,end);
    #define log_this(name,value)    cout<<name<<": "<<value<<endl;
    #define e4 10004
    #define e5 100005
    #define e6 1000006
    #define e7 10000007
    #define e9 1000000000
    #define INF 9999999
    using namespace std;
    int     to_int(string s)    {stringstream ss;ss<<s;int a;ss>>a;return a;}
    string  to_str(double a)    {stringstream ss;ss<<a;return ss.str();}
    
    int n,k;
    int ans[2005];
    int cost[2005][10];
    int preCan[2005][2005]; //记录[i+1,n)的元素能否使用j完美填充,-1未访问,0否,1是
    
    string ITB[] = {
        "1110111", "0010010", "1011101", "1011011", "0111010", "1101011", "1101111", "1010010", "1111111", "1111011"
    };
    
    int Cost(string org,string nto){
        int cost = 0;
        fr(i,7){
            int p = nto[i]-org[i];
            if(p<0){
                cost = -1;
                break;
            }else{
                cost+=p;
            }
        }
        return cost;
    }
    
    bool dfs(int i,int k){
        if(i==n&&k==0)  return preCan[i][k] = true;
        if(k<0 ||(i==n&&k>0))    return preCan[i][k] = false;
    
        r_frr(j,0,10){
            if(cost[i][j]!=-1){
                //cout<<i<<" "<<j<<" "<<cost[i][j]<<endl;
                ans[i] = j;
                bool hasf;
                int left = k-cost[i][j];
                if(preCan[i+1][left]==-1)   hasf = dfs(i+1,left);
                else hasf = preCan[i+1][left];
    
                if(hasf) return preCan[i][k] = hasf;
            }
        }
        return preCan[i][k] = false;;
    }
    
    int main(){
    
        cin.tie(0);
        //ios::sync_with_stdio(false);
        //cout<<setiosflags(ios::fixed)<<setprecision(0);
    
        while(cin>>n>>k){
            string inp;
            fr(i,n){
                cin>>inp;
                fr(j,10) cost[i][j] = Cost(inp,ITB[j]);
            }
            fr(i,n+1) fr(j,k+1) preCan[i][j] = -1;
    
            bool hasf = dfs(0,k);
            if(hasf){
                fr(i,n) cout<<ans[i];
                cout<<endl;
            }else{
                cout<<"-1"<<endl;
            }
        }
    
        return 0;
    }
    
  • 相关阅读:
    BZOJ 2300凸包+离线
    BZOJ 4140 凸包+二进制分组
    BZOJ 2178 Simpson积分
    BZOJ 4828 DP+BFS
    BZOJ 1845 Simpson积分
    BZOJ 1137 半平面交
    Codeforces 803G Periodic RMQ Problem ST表+动态开节点线段树
    Codeforces Round 411 Div.2 题解
    BZOJ 4530 LCT/线段树合并
    BZOJ 2946 SA/SAM
  • 原文地址:https://www.cnblogs.com/DOEMsy/p/12782709.html
Copyright © 2011-2022 走看看