• Codeforces Round #546 (Div. 2) 题解


    Codeforces Round #546 (Div. 2)

    题目链接:https://codeforces.com/contest/1136

    A. Nastya Is Reading a Book

    题意:

    一本书有n个章节,之后给出每个章节所在页数范围,然后有一个人来看书看了k页,问还有多少章节没看。

    题解:

    水题。模拟一下就好了。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 2e5+5;
    int n;
    int l[N],r[N];
    int main(){
        ios::sync_with_stdio(false);cin.tie(0);
        cin>>n;
        for(int i=1;i<=n;i++) cin>>l[i]>>r[i];
        int k;
        cin>>k;
        int p = lower_bound(l+1,l+n+1,k)-l;
        if(l[p]==k) cout<<n-p+1;
        else cout<<n-p+2;
        return 0;
    }
    View Code

    B. Nastya Is Playing Computer Games

    题意:

    有n个格子,每个格子一开始都有一个硬币,硬币上面都有一个石头。现在有一个人在k这个位置,问他需要多少次操作能将所有的硬币捡完。操作可以分为以下三类:

    1.左右移动一格;2.将当前硬币上面的石头扔向另外一个格子(可以自己选择);3.捡起当前的硬币。

    题解:

    思路就是将操作分开看,移动所需要的花费以及捡硬币所需要的花费。这里扔石头是有贪心思想的,也就是说我们尽可能地将石头扔向那些没有硬币的格子中。

    具体看代码吧:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 2e5+5;
    int n,k;
    int main(){
        ios::sync_with_stdio(false);cin.tie(0);
        cin>>n>>k;
        cout<<n + n+1 + n-1+min(n-k,k-1);
        //捡硬币,扔石头,和移动 
        return 0;
    }
    View Code

    C. Nastya Is Transposing Matrices

    题意:

    给出两个矩阵,现在你可以对第一个矩阵的任意一个子矩阵进行转置操作,即将行列对换,可以进行多次操作。最后问是否能够将第一个矩阵变为第二个矩阵。

    题解:

    观察转置操作,其实就是将一条对角线上面的数进行了重排列。那么我们就可以将一个较大矩阵的操作,变为许多2*2矩阵的转置操作(改变对角线)。

    所以我们只需要判断一下两个矩阵对角线上面的值是否一样就行了。

    代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 505;
    int n,m;
    int a[N][N];
    int b[N][N];
    vector <int> vec1,vec2;
    int main(){
        ios::sync_with_stdio(false);cin.tie(0);
        cin>>n>>m;
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>a[i][j];
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>b[i][j];
        int last=0;
        for(int k=2;k<=n+m;k++){
            vec1.clear();vec2.clear();
            int i,j;
            if(k<=1+m) i=1;
            else i=k-m;
            j = k-i;
            //cout<<endl<<endl;
            while(i<k && i<=n && j>=1){
                //cout<<i<<" "<<j<<endl;
                vec1.push_back(a[i][j]);
                vec2.push_back(b[i][j]);
                i++;j--;
            }
            sort(vec1.begin(),vec1.end());
            sort(vec2.begin(),vec2.end());
            int s=vec1.size();
            for(i=0;i<s;i++){
                if(vec1[i]!=vec2[i]){
                    cout<<"NO";
                    return 0;
                }
            }
        }
        cout<<"YES";
        return 0;
    }
    View Code

    D. Nastya Is Buying Lunch

    题意:

    有n个人从左到右站立,然后有m个规则:每个规则里面描述的就是,如果有一个人在另一个人前面,那么这两个人就可以交换位置。问最后一个人最多可以到多前面去。

    题解:

    这个题我一开始乱写一发过了70个点,后面认真想了下,就WA4了。。

    其实这个题可以发现一个数量关系,如果一个人目前的位置在pos处,那么如果后面有n-pos个人可以和他交换,那么他就肯定能和最后一个人交换。

    当然这里的n-pos是除开某些已经和最后一个人交换了的人的。所以从后扫一下就行了,具体见代码吧。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 5e5+5;
    int n,m;
    int a[N],cnt[N],p[N];
    vector <int> g[N];
    void adde(int u){
        for(auto v:g[u]) cnt[v]++;
    }
    int main(){
        ios::sync_with_stdio(false);cin.tie(0);
        cin>>n>>m;
        for(int i=1;i<=n;i++) cin>>a[i],p[a[i]]=i;
        for(int i=1;i<=m;i++){
            int u,v;
            cin>>u>>v;
            g[v].push_back(u);
        }
        int ans = 0;
        adde(a[n]);
        for(int i=n-1;i>=1;i--){
            if(cnt[a[i]]==n-i-ans) ans++;
            else adde(a[i]);
        }
        cout<<ans;
        return 0;
    }
    View Code

    E. Nastya Hasn't Written a Legend

    题意:

    给出n个数,然后给出n个数的权值以及对应的ki,现在有两种操作,一个是询问区间和,另一个就是对某个位置上的数加上x,然后对于所有后面的数,如果ai+1<ai+ki,就让ai+1=ai+ki

    题解:

    这个题需要转化一下,因为题目一开始保证了ai+1>=ai+ki的,然后令ti=k1+k2+...+ki,那么两边同时减去ti,最后变为ai+1-ti>=ai-ti-1,然后我们构造bi=ai-ti-1,所以题目中的条件就转化为了bi+1>=bi

    接下来再看题目中的操作,求和操作很简单,求出对应bi的和,然后减去加上的值就行了;然后就是加法操作,如果bi加上x,那么后面小于bi+x的都要变为bi+x,这里用线段树查询一下第一个大于等于bi+x的位置就行了,具体方法就是先看左子树,再看右子树。

    这个构造方法可行的原因就在于,如果有ai+1<ai+x+ki,那么也必然有bi+1<bi+x,这个比较显然,同时减去一个数并不改变等号。

    代码如下:

    #include <bits/stdc++.h>
    #define INF 999999999999999
    using namespace std;
    typedef long long ll;
    const int N = 2e5+5;
    int n;
    ll a[N],b[N],t[N],k[N],pre[N];
    struct Seg_Tre{
        int l,r;
        ll lazy,sum,mx;
    }tre[N<<2];
    void push_up(int rt){
        tre[rt].sum=tre[rt<<1].sum+tre[rt<<1|1].sum;
        tre[rt].mx=max(tre[rt<<1].mx,tre[rt<<1|1].mx);
    }
    void push_down(int rt){
        if(tre[rt].lazy!=INF){
            ll lzy=tre[rt].lazy;
            tre[rt<<1].sum=lzy*(tre[rt<<1].r-tre[rt<<1].l+1);
            tre[rt<<1|1].sum=lzy*(tre[rt<<1|1].r-tre[rt<<1|1].l+1);
            tre[rt<<1].mx=lzy;
            tre[rt<<1|1].mx=lzy;
            tre[rt].lazy=INF;
            tre[rt<<1].lazy=lzy;tre[rt<<1|1].lazy=lzy;
        }
    }
    void build(int rt,int l,int r){
        tre[rt].l=l;tre[rt].r=r;tre[rt].lazy=INF;
        if(l==r){
            tre[rt].sum=tre[rt].mx=b[l];
            return ;
        }
        int mid = l+r>>1;
        build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
        push_up(rt);
    }
    ll query_sum(int rt,int l,int r){
        int L=tre[rt].l,R=tre[rt].r;int mid=L+R>>1;
        if(l<=L&&R<=r){
            return tre[rt].sum;
        }
        push_down(rt);
        ll ans = 0;
        if(l<=mid) ans+=query_sum(rt<<1,l,r);
        if(r>mid) ans+=query_sum(rt<<1|1,l,r);
        push_up(rt);
        return ans ;
    }
    ll query_pos(int rt,ll val){
        int L=tre[rt].l,R=tre[rt].r;
        int mid=L+R>>1;
        if(L==R) return L;
        ll p;
        push_down(rt);
        if(tre[rt<<1].mx>=val) p=query_pos(rt<<1,val);
        else p=query_pos(rt<<1|1,val);
        return p;
    }
    void update(int rt,int l,int r,ll val){
        int L=tre[rt].l,R=tre[rt].r;
        int mid=L+R>>1;
        if(l<=L&&R<=r){
            tre[rt].lazy=val;
            tre[rt].sum=val*(R-L+1);
            tre[rt].mx=val;
            return ;
        }
        push_down(rt);
        if(l<=mid) update(rt<<1,l,r,val);
        if(r>mid) update(rt<<1|1,l,r,val);
        push_up(rt);
    }
    int main(){
        ios::sync_with_stdio(false);cin.tie(0);
        cin>>n;
        for(int i=1;i<=n;i++) cin>>a[i];
        for(int i=1;i<n;i++){
            cin>>k[i];
            k[i]+=k[i-1];
            pre[i]=pre[i-1]+k[i];
        }
        for(int i=1;i<=n;i++) b[i]=a[i]-k[i-1];
        build(1,1,n);
        int q,x,y;char c;
        cin>>q;
        while(q--){
            //getchar();
            cin>>c>>x>>y;
            if(c=='s'){
                ll ans = query_sum(1,x,y);
                cout<<ans+pre[y-1]-(x>=2?pre[x-2]:0)<< '
    ';
            }else{
                ll st = query_sum(1,n,n);
                ll now = query_sum(1,x,x)+y;
                ll r = query_pos(1,now);
                if(r==n && st<now) r=n+1;
                update(1,x,r-1,now);
                //cout<<x<<" "<<r<<" "<<now+y<< '
    ';
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    毕业设计(五)
    毕业设计:周计划任务(四)
    毕业设计:周计划任务(三)
    毕业设计:周计划任务(二)
    毕业设计:周计划任务(一)
    运行jar包
    常见算法
    mybatis入门
    策略模式
    java面2
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10549156.html
Copyright © 2020-2023  润新知