騰訊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 <bits/stdc++.h>
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<len;i++){
        ans+=(s[i]-'0')*pow(10,len-i-1);
    }
    return ans;
}
//得到l,r這個區間的串
string solve(int l,int r){
    string num="";
    int pos=l+1;
    while(pos<r&&str[pos]!='|'){
        num+=str[pos];
        pos++;
    }
    string temp="";
    pos++;
    while(pos<r){
        if(str[pos]=='['){
            int newl=pos;
            int newr=match[pos];
            //cout<<"debug "<<temp<<endl;
            temp+=solve(newl,newr);
            //cout<<"what "<<solve(newl,newr)<<endl;
            pos=match[pos]+1;
            //printf("pos %d\n",pos);
        }
        else{
            temp+=str[pos];
            pos++;
        }
        //cout<<"debug "<<temp<<endl;
    }
    int cnt=getint(num);
    //printf("cnt %d\n",cnt);
    //cout<<"debug "<<temp<<endl;
    string temp2=temp;
    for(int i=1;i<cnt;i++){
        temp+=temp2;
    }
    //cout<<"debug "<<temp<<endl;
    return temp;
}
signed main(){
    cin>>str;
    for(int i=0;i<str.size();i++)match[i]=-1;
    stack<int>s;
    for(int i=0;i<str.size();i++){
        if(str[i]=='['){
            s.push(i);
        }
        else if(str[i]==']'){
            int cur=s.top();s.pop();
            match[i]=cur;
            match[cur]=i;
        }
    }
    string ans="";
    int pos=0;
    while(pos<str.size()){
        if(str[pos]!='['){
            ans+=str[pos];
            pos++;
        }
        else{
            ans+=solve(pos,match[pos]);
            pos=match[pos]+1;
        }
    }
    cout<<ans<<endl;
    return 0;
}

[編程題]逛街

時間限制:C/C++ 2秒,其他語言4秒

空間限制:C/C++ 256M,其他語言512M

小Q在週末的時候和他的小夥伴來到大城市逛街,一條步行街上有很多高樓,共有n座高樓排成一行。

小Q從第一棟一直走到了最後一棟,小Q從來都沒有見到這麼多的樓,所以他想知道他在每棟樓的位置處能看到多少棟樓呢?(當前面的樓的高度大於等於後面的樓時,後面的樓將被擋住) 

思路:

裸的單調棧,左右維護一個單調遞減的單調棧,每次查看棧內元素個數就好了

#include <bits/stdc++.h>
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]);
    stack<int>s;
    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 <bits/stdc++.h>
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 <bits/stdc++.h>
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<b.l||(a.l==b.l&&a.r<b.r);
}
struct TreeNode{
    int l,r;
    int maxx;
}Tree[maxn<<2];
void Build(int root,int l,int r){
    Tree[root].l=l,Tree[root].r=r;
    if(l==r){
        Tree[root].maxx=0;
        return ;
    }
    int mid=(l+r)>>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));
    }
}
vector<int>v;
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;

}

 

發佈了216 篇原創文章 · 獲贊 15 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章