A. Find The Array

题意:给定一个数组a,你寻求一个数组b,使得相邻两项可以被整除,且 $2 \sum \limits_{i = 1}^{n} |a_i - b_i| \le S$

思路:可以发现,当我们把所有奇数项或偶数项都赋值为1,那么就可以满足整除,是奇数为1还是偶数为1,取决于奇数项的和大还是偶数项的和大,将大的为1,小的与a对应即可

diamond:

#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve(){
    int s1=0;
    int s2=0;
    int n;
    cin>>n;
    vector<int>g(n);
    for (int i = 0; i <n ; ++i) {
        cin>>g[i];
        if(i&1)s1+=g[i];
        else s2+=g[i];
    }
    if(s1<s2){
        for (int i = 0; i <n ; ++i) {
            if(i&1)cout<<'1'<<' ';
            else cout<<g[i]<<' ';
        }
    }
    else {
        for (int i = 0; i <n ; ++i) {
            if((i&1)==0)cout<<'1'<<' ';
            else cout<<g[i]<<' ';
        }
    }
    cout<<endl;
}
int32_t main() {
    int t;
    cin>>t;
    while (t--){
        solve();
    }
    return 0;
}

B. Busy Robot

题意:一个机器人在数轴上,0秒在0,会给它n个指令,一个指令含有两个值,ti和xi,表示他要在ti秒时往xi这个点走,假设他在1秒前往5,在2s接到一个指令前往1,那么这个指令会被忽略,因为1秒的指令还未结束,如果一个指令是成功的,那么就是在ti到t(i+1)的时间里,经过了xi,问成功指令有多少

思路:模拟,我们记录当前执行的指令的起点qd,和终点zd,以及指令结束的时间nexttime,lsttime记录的是执行的哪个指令,然后我们更新即可

  • 当我们当前指令的t在上一个执行的指令结束时间nexttime之后,我们执行当前指令,更新这些参数,如果nexttime<=a[i+1].t,那么就是成功的指令。

  • else,我们计算当前走到了哪儿,以及a[i+1].t走到了哪儿,x在两者之间,就是成功指令

    diamond:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    struct node{
    int t,x;
    };
    void solve(){
    int n;
    cin>>n;
    vector<node>a(n+1);
    
    for (int i = 0; i <n ; ++i) {
        cin>>a[i].t>>a[i].x;
    }
    a[n].t=1e15;
    int ans=0;
    int qd=0,zd=0,nexttime=0,lstime=0;
    for(int i = 0; i <n ; ++i) {
        if(a[i].t>= nexttime){
            nexttime=a[i].t+abs(a[i].x-zd);
            qd=zd,zd=a[i].x;
            lstime=i;
            if(nexttime<=a[i+1].t){
                ans++;
            }
        }
        else{
            if(qd>=zd){
                int y=qd-(a[i].t-a[lstime].t);
                int x=max(zd,qd-(a[i+1].t-a[lstime].t));
                if(a[i].x>=x&&a[i].x<=y){
                    ans++;
                }
    
            }
            else{
                int x=qd+a[i].t-a[lstime].t;
                int y=min(zd,qd+a[i+1].t-a[lstime].t);
                if(a[i].x>=x&&a[i].x<=y){
                    ans++;
                }
            }
        }
    }
    cout<<ans<<endl;
    }
    int32_t main() {
    int t;
    cin>>t;
    while (t--){
        solve();
    }
    return 0;
    }

    D. Program

    题意:初始值为0,给定一个字符串,操作分为+和-,+就是加一,-是减一,给q个询问,每个询问包含l和r,将l到r的操作忽略之后,执行字符串中的操作共可以得到几个值

    思路:假如- + - - + - - +,将1到8 忽略,只能得到0这一个值,由于操作是+1或-1,因此我们只需得到这个操作过程中的最大值和最小值,差+1就是答案,我们可以发现,当我们将中间的操作忽略之后,其实就是保留l-1之前的操作以及和r+1之后的操作,画图易知,进行一个前缀和,将r+1之后的数字加到l-1那个地方,对0到l取min和max,和操作后的r到n进行取min和max,求出答案,我们要考虑到没有右边的情况,以及max>=0,mi<=0;

    diamond:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    int b[200010],c[200010],lmax[200010],lmin[200010],rmax[200010],rmin[200010];
    int32_t main() {
    int t;
    cin>>t;
    while(t--){
        int n,k;
        cin>>n>>k;
        b[0]=0;
        for(int i=1;i<=n+5;i++){
            b[i]=0;
            c[i]=0;
            lmax[i]=LLONG_MIN;
            lmin[i]=LLONG_MAX;
            rmax[i]=LLONG_MIN;
            rmin[i]=LLONG_MAX;
        }
        lmax[0]=0;
        lmin[0]=0;
        rmin[n+1]=0;
        rmax[n+1]=0;
        string s;
        cin>>s;
        s="0"+s;
    
        for(int i=1;i<=n;i++){
            if(s[i]=='-'){
                b[i]=b[i-1]-1;
            }
            else{
                b[i]=b[i-1]+1;
            }
    //         cout<<i<<" "<<b[i]<<endl;
        }
        lmax[1]=b[1];
        lmin[1]=b[1];
        for(int i=2;i<=n;i++){
            //c[i]=c[i-1]+b[i];
            lmax[i]=max(lmax[i-1],b[i]);
            lmin[i]=min(lmin[i-1],b[i]);
        }
        rmax[n]=b[n];
        rmin[n]=b[n];
        for(int i=n-1;i>0;i--){
            rmax[i]=max(rmax[i+1],b[i]);
            rmin[i]=min(rmin[i+1],b[i]);
        }
        for(int i=1;i<=k;i++){
            int l,r;
            cin>>l>>r;
            int d=b[r]-b[l-1];
            int lma=lmax[l-1];
            int lmi=lmin[l-1];
            int rma=rmax[r+1];
            int rmi=rmin[r+1];
            if(r!=n) {
                rma -= d;
                rmi -= d;
            }
            int mi;
            if(r!=n)
             mi=min(lmi,rmi);
            else mi=lmi;
            int ma;
            if(r!=n)
             ma=max(lma,rma);
            else ma=lma;
    //////            if(ma)ma=0;
    //////            if(mi==LLONG_MIN)mi=0;
    //            cout<<d<<' '<<mi<<' '<<ma<<endl;
    //            cout<<lmin[1]<<endl;
    //            cout<<lmi<<' '<<lma<<endl;
            if(ma<0)ma=0;
            if(mi>0)mi=0;
            cout<<ma-mi+1<<endl;
        }
    
    }
    return 0;
    }

    E. No More Inversions

    题意:给一个n和k,a排列是这样排列的,假如k=5,n为8排列就为1,2,3,4,5,4,3,2;8个元素,然后我们要求出一个p数组,映射关系为,$b[i]=p[a[i]]$,得到的b数组要求是逆序对要<=a序列的逆序对个数,且b数组的字典序最大,我们要求出p数组

    思路:规律题,我们可以发现当我们这样排列时即可,k=5,n=8;末尾是5 4 3 2,前面是1,得到1 5 4 3 2,然后得到b数组,1 5 3 4 2 3 4 5 ,我们得到的符合条件

    diamond:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    void solve(){
    int n,k;
    cin>>n>>k;
    int hou=n-k+1;
    int qian=k-hou;
    for (int i = 1; i <=qian ; ++i) {
        cout<<i<<' ';
    }
    while (hou--){
        cout<<k--<<' ';
    }
    cout<<'\n';
    }
    int32_t main() {
    int t;
    cin>>t;
    while (t--){
        solve();
    }
    }

    F. Ceil Divisions

    题意:给1个1到n的顺序列,我们要将这个数组变为n-1个1和一个2的序列,我们的操作是这样的,选择a[x],和a[y],将$a_x = \left\lceil \frac{a_x}{a_y} \right\rceil$,问至多操作n+5次,如何操作才能得到答案

    思路:假设我们得到的是1到200000,我们对他开方得到,448,22,5,3,3因此我们对这些数分别这样操作,200000/448,得到448,然后/448,得到1,这样我们就得到了9次即可,然后我们加上n-8,这样我们就可以在n+5次之内得到答案

    diamond:

    #include "bits/stdc++.h"
    #define endl '\n'
    using namespace std;
    void solve() {
    vector<int>ve ;
    map<int,int>mp;
    int n;
    cin >> n;
    if (n == 3) {
        cout << 2 << endl;
        for (int i = 0; i < 2; i++) cout << 3 << " " << 2 << endl;
        return;
    }
    int d = n;
    while (d != 3){
        ve.push_back(d);
        mp[d]=1;
        double g=(int)floor(sqrt(d)) + 1;
        d=(int )g;
        if(g*g==d*d);
        else d++;
    }
    ve.push_back(3);
    mp[3]=1;
    cout<<n+ve.size()-2<<endl;
    for(int i=4;i<=n;i++){
        if(mp[i]!=1){
            cout<<i<<" "<<n<<endl;
        }
    }
    for (int i = 0; i <ve.size() ; ++i) {
        if(ve[i]==3){
            cout<<ve[i]<<' '<<2<<endl;
            cout<<ve[i]<<' '<<2<<endl;
        }
        else {
            cout << ve[i] << ' ' << ve[i + 1] << endl;
            cout << ve[i] << ' ' << ve[i + 1] << endl;
        }
    }
    }
    signed main() {
    int t;
    cin >> t;
    while (t--) solve();
    }
     
posted on 2023-09-15 18:23  IR101  阅读(9)  评论(0编辑  收藏  举报  来源