多校01_补题记录

Posted anonym

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多校01_补题记录相关的知识,希望对你有一定的参考价值。

1001

题意:int n ,存在x,y,z∈int,满足x+y+z=n,s.t. x*y*z取到最大值,求最大值

最早是用猜的...3的倍数显而易见,试了前20个发现凡4的倍数都能拆成1 1 2的倍数之和..._(:з」∠)_...

正经解法:

   令r=n/x ,s=n/y ,t=n/z ,则 n/r+n/s+n/t=n ,即1/r+1/s+1/t=1

  求解可得(3,3,3),(2,4,4),(2,3,6)三种情况,即3|n or 4|n

AC代码:

技术分享图片
 1 #include<cstdio>
 2 #include<iostream>
 3 
 4 using namespace std;
 5 int T,n;
 6 
 7 int main(){
 8     long long t,ans;
 9 
10     scanf("%d",&T);
11     while(T--){
12         scanf("%d",&n);
13         t=0;
14         if(n%3==0){
15             t=n/3;
16             ans=t*t*t;
17             printf("%lld
",ans);
18         }
19         else if(n%4==0){
20             int a;
21             t=n/4;
22             ans=t*t*(2*t);
23             printf("%lld
",ans);
24         }
25         else printf("-1
");
26     }    
27     return 0;
28 } 
1001

 

1002

题意:给n个由左右小括号组成的字符串,调整字符串间的顺序使得连成的长字符串的Balanced Sequence长度最长(不要求连续),求最长长度

思路:先求每个字符串内的平衡串长度,再对字符串中不在平衡串内的括号组成的子串进行排序(贪心)计算排序后的新的平衡串长度,两部分长度之和为题目所要求的长度

  贪心思路:上述第二部分的子串只有三种可能:只有 ‘(’ ;只有 ‘)‘ ;或者x个 ‘)‘ 连y个 ‘(‘ 。因此只需要对第三种情况进行排序,具体思路详见代码备注

AC代码:

技术分享图片
//AC
//重点在于给每个字符串中余下的括号进行排序,cmp改到快死掉.....如果不是有数据...我已经去世了.... 
//1.贪心:对于同时具有左右括号的部分,
//        把左括号多、右括号少的放前面,尽量少的抵消左括号确保后续更多的右括号能尽可能消去 
//2.排序:先处理都大于0的情况,然后处理其一大于0,最后才是全小于0,顺序不能变 
#include<iostream>
#include<cstdio>
#include<stack>
#include<cstring>
#include<algorithm>

using namespace std;
int t,n;
int tagl,tagr,ans;
char s[100005];
stack<char>st;
struct node{
    int l,r;
}a[100005];
bool cmp(node x,node y){       //注意比较的顺序!!! 
    if(x.l+x.r>=0&&y.l+y.r>=0) return x.r>y.r;
    if(x.l+x.r>=0||y.l+y.r>=0)return x.l+x.r>y.l+y.r; 
    if(x.l+x.r<=0&&y.l+y.r<=0) return x.l>y.l;
}

int main(){
//    freopen("1002.in", "r", stdin);
//   freopen("1002t.out", "w", stdout);
    cin>>t;
    while(t--){
        cin>>n;
        tagl=tagr=0;
        int k=0;
        ans=0;
        for(int i=0;i<n;i++){
            cin>>s;
            int len=strlen(s);
            for(int j=0;j<len;j++){         
                if(s[j]==()
                    st.push(s[j]);
                else{
                    if(!st.empty()&&st.top()==(){
                        ans++;st.pop();
                    }
                    else st.push(s[j]);
                }    
            }                                         
                        int ll=0,rr=0;                   
            while(!st.empty()){
                if(st.top()==() ll++; 
                else rr--;
                st.pop();
            }                              
            if(ll==0||rr==0){               
                tagl+=ll;tagr+=rr;            
            }
            else{                            
                a[k].l=ll;a[k].r=rr; k++;       
            }                               
        }
        
        sort(a,a+k,cmp);
        for(int i=0;i<k;i++){              
            if(tagl<0) tagl=0;
            if(tagl+a[i].r<0){
                ans+=tagl;
                tagl=a[i].l;
            }
            else{
                ans-=a[i].r;
                tagl+=a[i].r+a[i].l;
            }
        }                           
        ans+=min(-tagr,tagl);         
        cout<<2*ans<<endl;
        
    }
}            
1002

1003

题意:给3n个点,保证不存在三点共线的情况,输出任一种组成n个不相交三角形的情况

思路:所有点坐标按x轴排序,然后顺序输出,over

AC代码:

技术分享图片
#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;
int t,n,np;
struct node{
    int num;
    int x,y;
}tri[3005];
bool cmp(node a,node b){
    if(a.x==b.x) return a.y<b.y;
    return a.x<b.x;
}

int main(){
    cin>>t;
    while(t--){
        cin>>n;
        np=3*n;
        for(int i=0;i<np;i++){
            cin>>tri[i].x>>tri[i].y;
            tri[i].num=i+1;        
        }
        sort(tri,tri+np,cmp);      
        for(int i=0;i<np;){      
            cout<<tri[i].num<<" "<<tri[i+1].num<<" "<<tri[i+2].num<<endl;
            i=i+3;
        }
    }    
}
1003

1004

题意:有一个长度为n的数组,已知几个事实:给定闭区间范围内的数互不相等,求满足事实的最小字典序数组

思路:对区间排序,对任意点可得到覆盖该点的最大区间。最小字典序数组意味着从第一个位置开始往后每个位置取当前满足条件的最小值,用set储存当前可以使用的数,在某一闭区间范围内使用一个删一个,flag标记上一次开始删除元素的位置,遇到新的区间时将flag->区间左端点的范围内的数字加入set

AC代码:

技术分享图片
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<set>

using namespace std;
int t,n,m,ans[100005];
struct node{
    int st,ed;
}a[100005];
bool cmp(node x,node y){
    if(x.st!=y.st) return x.st<y.st;
    return x.ed>y.ed;
}
set<int> s;

int main(){
    cin>>t;
    while(t--){
        s.clear();
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            s.insert(i);
        }
        for(int i=0;i<m;i++){
            cin>>a[i].st>>a[i].ed;    
        }
        sort(a,a+m,cmp);      

        int k=1,flag=1;
        for(int i=0;i<m;i++){
            if(k<a[i].st){
                while(k<a[i].st){
                    ans[k]=1;k++;
                }
                while(flag<a[i].st){
                    s.insert(ans[flag]);
                    flag++;
                }
                while(k<=a[i].ed){
                    ans[k]=(*s.begin());
                    k++;
                    s.erase(*s.begin());
                }
            }
            else if(k>a[i].ed){
                continue;
            }
            else{
                while(flag<a[i].st){
                    s.insert(ans[flag]);
                    flag++;
                }
                while(k<=a[i].ed){
                    ans[k]=(*s.begin());
                    s.erase(*s.begin());
                    k++;
                }
            }    
        }
        while(k<=n) ans[k++]=1;    
        
        cout<<ans[1];
        for(int i=2;i<=n;i++)cout<<" "<<ans[i];
        cout<<endl; 
    }
}
1004

1011

题意:求北京时间在给定时区的当地时间

思路:模拟

AC代码

技术分享图片
#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;
int t,a,b,h,m,xh,xm;
char s[10];

int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d %d",&a,&b);
        scanf("%s",&s);
        int len=strlen(s);                   
        int i=4;
        xh=0;
        xm=0;
        while(s[i]!=.){              
            xh=xh*10+(s[i]-0);
            i++;                                       
            if(i>=len) break;
        }
        if(s[len-2]==.) xm=(s[len-1]-0)*6;
        if(s[3]==-) {
            xh=xh*(-1);
            xm=xm*(-1);
        }
                                          
        h=a+(xh-8);                         
        m=b+xm;
        if(m>=60) {h++;m=m-60;}
        else if(m<0){h--;m=60+m;}
        if(h>=24){h=h-24;}
        else if(h<0){h=24+h;}          
        
        printf("%02d:%02d
",h,m);
        
    }
}
1011

 

以上是关于多校01_补题记录的主要内容,如果未能解决你的问题,请参考以下文章

补题日记[2022牛客暑期多校4]A-Task Computing

补题日记[2022牛客暑期多校4]A-Task Computing

2022牛客多校3补题

2022牛客多校3补题

2022牛客多校3补题

2022牛客多校3补题