周总结(第一周)

3月份3个星期

*** 三个星代表不会
** 再做 * 加强

题目1-完全二叉树(记忆)

考察数据结构
完全二叉树的深度dep=log2(N+1)+1
完全二叉树节点的深度depi=ceil(log2(i+1))向上舍入

完全二叉树的层次遍历,遍历每层的二叉树计算基础每层的总和,然后找出最大的和。用到log2()函数,计算以2为底的对数,还有ceil()向上取整函数,头文件是cmath.
完全二叉树的深度h与节点数N的关系为h=log2(N+1).

#include 
#include 
using namespace std;

int main()
{
   int n,x,d;
   long long int num=0;
   cin>>n;
   long long arr[10005] = { 0 };//初始化数组
   int dep = log2(n + 1);//二叉树的深度
   for(int i=1;i<=n;i++){
        cin>>x;//直接将数据输入进去就可以
    int id = ceil(log2(i + 1));//计算当前的数据所在的深度
    arr[id]+=x;//把对应深度的数相加
   }
   for(int i=1;i<=dep+1;i++){
    if(num<arr[i]){//比较得出最大值得的最小深度
        num=arr[i];
        d=i;
    }
   }
   cout<<d<<endl;
    return 0;
}

注意:直接输入数据就ok,将各深度相同的二叉树的权值进行相加;深度用数组的下标表示即可。

再做一遍:

#include 
#include 
using namespace std;
int a[10004];
int main()
{
    int N,x;
    cin>>N;

    int dep = log2(N + 1);
    for(int i=1;i<=N;i++)
    {
        cin>>x;
        int id = ceil(log2(i + 1));
        a[id]+=x;
    }
    int maxn=-1;
    int d=0;
    for(int i=1;i<=dep;i++)//错误代码
    {
        if(maxn<a[i]) {
                maxn=a[i];
                d=i;
        }

    }
    cout<<d<<endl;
    return 0;
}

周总结(第一周)_第1张图片
完全二叉树总共的深度dep=log2(N+1)+1
完全二叉树的结点的深度dep=ceil(log2(i+1))向上舍入最近的数

修改:

  for(int i=1;i<=dep+1;i++)
   {
        if(maxn<a[i]) {
                maxn=a[i];
                d=i;
        }

    }

题目2-后缀表达式 **

有点不熟悉,不清楚还有会有括号的出现
利用队列

这个题“()”的存在是没有想到的。

错误代码;
应该考虑几种情况;

#include 
#include 
using namespace std;
int main()
{
  int n,m;
  cin>>n>>m;
  long long int a[n+m+10];
  for(int i=1;i<=n+m+1;i++){
    cin>>a[i];
  }
  sort(a+1,a+1+n);
  long long int sum=0;
  for(int i=1;i<=m;i++){
    sum-=a[i];
  }
  for(int i=m+n+1;i>=m+1;i--){
    sum+=a[i];
  }
  cout<<sum<<endl;
  return 0;
}
#include 
/*
1.不含负数
  单数减号1-(1-1-1)=1-1+1+1 相当于减掉一个最小的
  双数减号1+1-(1-1)
  总结减号数>=1都可以转换成减去最小的数
2.含有负数(例如:1-[-1+(-1)]-(-1))
  (假设:负数f个,加号p个,减号m个,数n个,n=p+m+1)(f>0,m>=1,n-m>=1,f<=n)
  1个减号可以把p+1即n-m个负数转成正数,剩余的负数f-(n-m)个负数,此时减号还有m-1个(用到了一个)
  剩余的每个负数都由一个减号去转换。先不考虑(f-(n-m)大小,即先不考虑剩余负数的个数)

  a.当f-(n-m)0,因为m>=1,所以f-(n-m)m-1,f>n-1,即f>=n,即f==n,再由上述剩余的负数为m个,此时减号为m-1个,
    此时没有了减号,还有一个负数
     (绝对值总和减到取绝对值最小啊的那个负数的两倍)
  c.当f-(n-m)=m-1,此时没有负数也没有负号了,输出所有的数的绝对值之和

  根据a,b,c得
     当f==n(所有数全为负数)时,绝对值总和减到取绝对值最凶啊的那个负数的两倍
     当f!=n时,输出所有数的绝对值之和
*/
using namespace std;
int p,n,m;
long long sum=0,rsum=0;//sum是绝对值和,rsum是真实值和
int fu=0,min;
long long num[200001],fnum[200001];
int main()
{
  // 请在此输入您的代码
  cin>>p>>m;
  n=p+m+1;
  for(int i=0;i<n;i++)
  {
    cin>>num[i];
    if(num[i]<0){
      fnum[fu]=num[i];
      fu++;//记录负数的个数
      sum-=num[i];//计算绝对值之和
    }else
      sum+=num[i];
    rsum+=num[i];//计算真实值之和
  }
  if(m==0){//所有都是加号
    cout<<rsum;
  }else{//存在减号
    sort(num,num+n);
    if(fu==0){
      cout<<sum-2*num[0];
    }else{
      if(fu!=n){//存在负数存在减号
        cout<<sum;
      }else{//全为负数
        sort(fnum,fnum+fu);
        cout<<sum-(-2*fnum[fu-1]);
      }
    }
  }
  return 0;
}

题目3-迷宫 *

考察深搜广搜的典型题目
利用队列,出对入队

#include 
using namespace std;
int n,m;
string Map[500];
const int d[4][2]={{1,0},{0,-1},{0,1},{-1,0}};
const string dd="DLRU";//按照字典序增序
struct node {
    int i,j;
    string ans;//到达该节点需要的路径
};
queue<node> q;
void BFS()
{
    node s;
    s.i=0,s.j=0;s.ans="";
    Map[0][0]='1';
    q.push(s);//将第一个节点放入
    while(!q.empty())
    {
        node a=q.front(),b;//队列非空,取出队首
        int x=a.i;
        int y=a.j;
        q.pop();//弹出队首
        if(x==n-1&&y==m-1)//如果是最后一个就输出结果
        {
            cout<<a.ans.length()<<endl;
            cout<<a.ans<<endl;
            break;
        }
        for(int i=0;i<4;i++){//取出队首后,遍历队首四个方向
            int newx=x+d[i][0];
            int newy=y+d[i][1];
            if(newx<0||newy<0||newx>=n||newy>=m) continue;//越界.pass
            if(Map[newx][newy]=='1') continue;//走过,pass
            b.ans=a.ans+dd[i];//赋值,将该节点放入队列
            b.i=newx,b.j=newy;//赋值
            Map[newx][newy]='1';//赋值
            q.push(b);//放入队列
        }
    }
}
int main()
{
   /* cin>>n>>m;
    for(int i=0;i>Map[i];
    }
    BFS();*/
    cout<<"DDDDRRURRRRRRDRRRRDDDLDDRDDDDDDDDDDDDRDDRRRURRUURRDDDDRDRRRRRRDRRURRDDDRRRRUURUUUUUUULULLUUUURRRRUULLLUUUULLUUULUURRURRURURRRDDRRRRRDDRRDDLLLDDRRDDRDDLDDDLLDDLLLDLDDDLDDRRRRRRRRRDDDDDDRR"<<endl;
    return 0;
}

题目4-灵能传输 ***

题目-灵能传输

B站视频

#include 

using namespace std;
/*
ai-1 ,ai, ai+1 ---> ai-1+ai,-ai,ai+1+ai
si-1 ,si, si+1 ---> si, si-1,si
s0,s1,s2,s3,,,,,sn

*/
typedef long long ll;
const int N=300010;

int n;
ll s[N],a[N];
bool st[N];
int main()
{
    int T;
    cin>>T;
    while(T--){
    memset(s,0,sizeof(s));
    memset(a,0,sizeof(a));
     memset(st,0,sizeof(st));
    cin>>n;
    s[0]=0;
    for(int i=1;i<=n;i++){
        cin>>s[i];
        s[i]+=s[i-1];
    }
    ll s0=s[0],sn=s[n];
    if(s0>sn)swap(s0,sn);//?
    sort(s,s+1+n);
    for(int i=0;i<=n;i++){
        if(s[i]==s0)
        {
            s0=i;
            break;
        }
    }
    for(int i=0;i<=n;i++){
        if(s[i]==sn)
        {
            sn=i;
            break;
        }
    }
    //隔一个

    int l=0;
    int r=n;
    for(int i=s0;i>=0;i-=2)
    {
        a[l++]=s[i];
        st[i]=true;
    }
    for(int i=sn;i<=n;i+=2)
    {
        a[r--]=s[i];
        st[i]=true;
    }
    for(int i=0;i<=n;i++)
    {
        if(!st[i])
        {
            a[l++]=s[i];
            st[i]=true;
        }
    }
    ll res=0;
    for(int i=1;i<=n;i++){
        res=max(res,abs(a[i]-a[i-1]));
    }
    cout<<res<<endl;
    }
    return 0;
}

题目5-外卖店优先级 **

内存空间大小的问题,是否使用结构体

#include 
#include 
using namespace std;
const int N=10010;
int a[N][N];
//(10000 0000+20000 )*4(int)=4 0004 0000
//256M题目要求的空间,即2^8*z^20=256*1048567=2 6843 3152
int main()
{
    int n,m,t;
    cin>>n>>m>>t;
    int ts,id;
    memset(a,0,sizeof(a));
    for(int i=1;i<=m;i++)
    {
        cin>>ts>>id;
        a[ts][id]+=2;
    }
    int sum[n+1]={0};
    int b[n+1]={0};
    for(int i=1;i<=t;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(a[i][j]==0&&sum[j]!=0)
            {
                sum[j]-=1;
                if(sum[j]<=3) b[j]=0;
            }
            sum[j]+=a[i][j];
            if(sum[j]>5) b[j]=1;
        }
    }
    int ans=0;
    for(int j=1;j<=n;j++)
    {
        //cout<
        if(sum[j]>5||(sum[j]>3&&b[j]==1)) ans++;
    }
    cout<<ans<<endl;
    return 0;
}

周总结(第一周)_第2张图片
利用结构体

#include 
#include 
using namespace std;
const int N=100005;
struct node
{
    int ts,id;
}a[N];
int ans=0;
int sum[N];//当前优先
int last[N];//这家店的上一次订单的时刻
bool hz[N];
bool cmp(node x,node y)
{
   if(x.ts==y.ts) return x.id<y.id;
   return x.ts<y.ts;
}
int main()
{
    int n,m,t;
    cin>>n>>m>>t;
    int sk,bh;
    for(int i=1;i<=m;i++)
    {
        cin>>a[i].ts>>a[i].id;
    }
    sort(a+1,a+m+1,cmp);
    //求优先度
    sk=0;
//    for(int i=1;i<=m;i++)
//       cout<
    for(int i=1;i<=m;i++)
    {
        //当前时刻有订单的信息
        sk=a[i].ts;
        bh=a[i].id;
        if(sk!=last[bh]){//当前时刻与上一个时刻
            sum[bh]=sum[bh]-(sk-last[bh]-1);//当前优先度
        }
        if(sum[bh]<0) sum[bh]=0;
        if(sum[bh]<=3) hz[bh]=0;
        sum[bh]+=2;
        if(sum[bh]>5) hz[bh]=1;
        last[bh]=sk;
    }
    for(int i=1;i<=n;i++){
        if(last[i]<t){
            sum[i]-=t-last[i];
        }
        if(sum[i]<=3){
            hz[i]=0;
        }
    }
      for(int i=1;i<=n;i++){
        if(hz[i]) ans++;
      }
      cout<<ans<<endl;
    return 0;
}

题目6-修改数组

该题注意循环中的时间优化,还可以使用并查集

没有使用并查集
循环没有优化超时了

做法0.5:

#include 

using namespace std;
const int N=1000010;
long long int a[N];
//256*2^20=268,435,456
//long long int 占8字节内存 ,没有超内存
int main()
{
    int n,x;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>x;
            while(a[x]!=0)
         {
            x++;
         }
        cout<<x<<" ";
        a[x]=1;
    }
    cout<<endl;
    return 0;
}

周总结(第一周)_第3张图片

做法1:

将循环进行优化

#include 

using namespace std;
const int N=1000010;
long long int a[N];
//256*2^20=268,435,456
//long long int 占8字节内存 ,没有超内存
int main()
{
    int n,x;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>x;
            while(a[x]!=0)
         {
           a[x]++;
           x+=(a[x]-1);
         }
        cout<<x<<" ";
        a[x]++;
    }
    cout<<endl;
    return 0;
}

周总结(第一周)_第4张图片

你可能感兴趣的:(蓝桥杯,算法,c++,蓝桥杯)