腾讯2020校园招聘-后台&综合-第一次笔试题目解析

[编程题]压缩算法

时间限制:C/C++ 2秒,其他语言4秒

空间限制:C/C++ 256M,其他语言512M

小Q想要给他的朋友发送一个神秘字符串,但是他发现字符串的过于长了,于是小Q发明了一种压缩算法对字符串中重复的部分进行了压缩,对于字符串中连续的m个相同字符串S将会压缩为[m|S](m为一个整数且1<=m<=100),例如字符串ABCABCABC将会被压缩为[3|ABC],现在小Q的同学收到了小Q发送过来的字符串,你能帮助他进行解压缩么? 

思路:

大模拟,递归的将所有[]区间的内容暴力转换就好了,不得不说这个题放第一个比较折磨人

#include 
using namespace std;

string str;
const int maxn=1e5+10;
int match[maxn];
int getint(string s){
    int len=s.size();
    int ans=0;
    for(int i=0;i>str;
    for(int i=0;is;
    for(int i=0;i

[编程题]逛街

时间限制:C/C++ 2秒,其他语言4秒

空间限制:C/C++ 256M,其他语言512M

小Q在周末的时候和他的小伙伴来到大城市逛街,一条步行街上有很多高楼,共有n座高楼排成一行。

小Q从第一栋一直走到了最后一栋,小Q从来都没有见到这么多的楼,所以他想知道他在每栋楼的位置处能看到多少栋楼呢?(当前面的楼的高度大于等于后面的楼时,后面的楼将被挡住) 

思路:

裸的单调栈,左右维护一个单调递减的单调栈,每次查看栈内元素个数就好了

#include 
using namespace std;

const int maxn=1e5+10;
int a[maxn];
int ans[maxn];
signed main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    stacks;
    for(int i=1;i<=n;i++){
        ans[i]+=s.size();
        //printf("left %d\n",s.size());
        while(!s.empty()&&s.top()<=a[i])s.pop();
        s.push(a[i]);
    }
    while(s.size())s.pop();
    for(int i=n;i>=1;i--){
        ans[i]+=s.size();
        //printf("right %d\n",s.size());
        while(!s.empty()&&s.top()<=a[i])s.pop();
        s.push(a[i]);
    }
    for(int i=1;i<=n;i++){
        printf("%d ",ans[i]+1);
    }
    return 0;
}

[编程题]假期

时间限制:C/C++ 2秒,其他语言4秒

空间限制:C/C++ 256M,其他语言512M

由于业绩优秀,公司给小Q放了 n 天的假,身为工作狂的小Q打算在在假期中工作、锻炼或者休息。他有个奇怪的习惯:不会连续两天工作或锻炼。只有当公司营业时,小Q才能去工作,只有当健身房营业时,小Q才能去健身,小Q一天只能干一件事。给出假期中公司,健身房的营业情况,求小Q最少需要休息几天。

思路:

这个题挺有意思,因为每天只有三种状态:休息,工作或者健身房,所以dp[i][0,1,2]分别表示前i天最后一天在休息,工作或者健身房的最小休息日,转移就很好想了:

如果第i天工作,那一定是从昨天休息或者健身房转移过来;

如果第i天健身,那一定是从昨天工作或者休息转移过来;

否则,第i天休息,任何状态都可以转移过来,天数++。

#include 
using namespace std;

const int maxn=1e5+10;
int dp[maxn][5];
int a[maxn],b[maxn];
signed main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)scanf("%d",&b[i]);
    for(int i=0;i<=n;i++){
        for(int j=0;j<=3;j++)dp[i][j]=1e9;
    }
    for(int i=0;i<=3;i++)dp[0][i]=0;
    for(int i=1;i<=n;i++){
        if(a[i]==0&&b[i]==0){
            int ans=min(dp[i-1][0],min(dp[i-1][1],dp[i-1][2]));
            dp[i][0]=dp[i][1]=dp[i][2]=ans+1;
        }
        else{
            dp[i][0]=min(min(dp[i-1][1],dp[i-1][2]),dp[i-1][0])+1;
            if(a[i]==1){
                dp[i][1]=min(dp[i-1][2],dp[i-1][0]);
            }
            if(b[i]==1){
                dp[i][2]=min(dp[i-1][1],dp[i-1][0]);
            }
        }
    }
    int ans=1e9;
    for(int i=0;i<=2;i++){
        ans=min(ans,dp[n][i]);
    }
    printf("%d\n",ans);
    return 0;
}

[编程题]视野争夺

时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 256M,其他语言512M

小Q在进行一场竞技游戏,这场游戏的胜负关键就在于能否能争夺一条长度为L的河道,即可以看作是[0,L]的一条数轴。

这款竞技游戏当中有n个可以提供视野的道具−真视守卫,第i个真视守卫能够覆盖区间[xi,yi]。现在小Q想知道至少用几个真视守卫就可以覆盖整段河道

思路:

经典区间覆盖问题,我用线段树+离散化这种笨方法就好了。

将区间按照左端点排序,维护一个当前能到达的最远点maxx,那么当前向L扩张的,一定是左端点在[0,maxx],且右端点最大的那个区间会被我选定,所以线段树维护区间最大值,记得离散化,每次查询更新maxx就好了。

#include 
using namespace std;

const int maxn=2e5+10;
struct Node{
    int l,r;
}node[maxn];
int cmp(const Node a,const Node b){
    return a.l>1;
    Build(root<<1,l,mid);
    Build(root<<1|1,mid+1,r);
}
void update(int root,int pos,int val){
    if(Tree[root].l==Tree[root].r){
        Tree[root].maxx=val;
        return ;
    }
    int mid=(Tree[root].l+Tree[root].r)>>1;
    if(pos<=mid){
        update(root<<1,pos,val);
    }
    else{
        update(root<<1|1,pos,val);
    }
    Tree[root].maxx=max(Tree[root<<1].maxx,Tree[root<<1|1].maxx);
}
int query(int root,int l,int r){
    if(Tree[root].l>=l&&Tree[root].r<=r){
        return Tree[root].maxx;
    }
    int mid=(Tree[root].l+Tree[root].r)>>1;
    if(r<=mid){
        return query(root<<1,l,r);
    }
    else if(l>mid){
        return query(root<<1|1,l,r);
    }
    else{
        return max(query(root<<1,l,mid),query(root<<1|1,mid+1,r));
    }
}
vectorv;
int getid(int cur){
    return lower_bound(v.begin(),v.end(),cur)-v.begin()+1;
}
signed main(){
    int n,L;
    scanf("%d%d",&n,&L);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&node[i].l,&node[i].r);
        v.push_back(node[i].l);
        v.push_back(node[i].r);
    }
    sort(node+1,node+n+1,cmp);
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
    Build(1,1,v.size());
    for(int i=1;i<=n;i++){
        update(1,getid(node[i].l),node[i].r);
    }
    int maxx=0;
    bool flag=true;
    int ans=0;
    while(maxx<=L){
        int maxr=query(1,0,getid(maxx));
        if(maxr<=maxx){
            flag=false;
            break;
        }
        else{
            maxx=maxr;
            ans++;
        }
    }
    if(flag){
        printf("%d\n",ans);
    }
    else{
        puts("-1");
    }
    return 0;

}

 

你可能感兴趣的:(工作,补题)