if-I-can-fly

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

1.寄包柜

 

 

 看到题目最容易想到开二位数组

但数据量过大,因此需要map

#include <bits/stdc++.h>
using namespace std;
map<int,map<int,int> >a;

这里开了一个map,a的第一个下标是一个int类型的key(代表柜子位置),第二个下标是里面map的key(柜子上的格子号),里面map的value就是储存的值

含义类似于两个地址叠加,合起来指向存储的东西

因为是两个地址,所以就不会出现二维数组无用空间开太大的问题,问题就解决了

代码如下

int main()
{
    int n,q;
    int did,i,j,k;
    cin>>n>>q; 
    for(int t=0;t<q;t++)
    {
        cin>>did;
        if(did==1)
        {
            cin>>i>>j>>k;
            a[i][j]=k;
        }
        else if(did==2)
        {
            cin>>i>>j;
            cout<<a[i][j]<<endl;
        }
    }
   return 0;
}

2.括号序列

 

 

 

 

该题重在读懂题

注意以下几个要点

1.要依据右括号来判断是否成对

2.若出现([)或[)]这种夹不同括号的情况则要全部自成对(除非里面不同括号已经成对了)

因此从左到右依据右括号判断,还可规避在判断外部括号时,内部括号还不知道有没有成对的问题

#include<bits/stdc++.h>
using namespace std;
int b[10000]={0};
int main(void)
{
    char a[10000];
    cin>>a;
    int l=strlen(a);
    for(int i=0;i<l;i++)
    {
//从右括号判断是否成对,是则在b数组中对应变成1
        if(a[i]==')')
        {
            for(int j=i-1;j>=0;j--)
            {
                if(a[j]=='['&&b[j]==0)break;
                else if(a[j]=='('&&b[j]!=1)
                {
                    b[i]=1;
                    b[j]=1;
                    break;
                }
            }
        }
        else if(a[i]==']')
        {
            for(int j=i-1;j>=0;j--)
            {
                if(a[j]=='('&&b[j]==0)break;
                if(a[j]=='['&&b[j]!=1)
                {
                    b[i]=1;
                    b[j]=1;
                    break;
                }
            }
        }
    }
//输出
    for(int i=0;i<l;i++)
    {
        if(b[i]==1)cout<<a[i];
        else
        {
            if(a[i]=='(')cout<<"()";
            else if(a[i]=='[')cout<<"[]";
            else if(a[i]==']')cout<<"[]";
            else cout<<"()";
        }
    }
    return 0;
}

3.后缀表达式

 

以堆栈的方式将数字储存进数组里

#include<bits/stdc++.h>
using namespace std;
int a[1005];//a的作用类似于栈
int main()
{
    char c;
//now存数,i记a中数字个数
    int i=0,now=0;
    while(cin>>c&&c!='@'){
        if(c>=48&&c<=57)
        {
            now*=10;
            now+=c-48;
        }
//存数,以类似堆栈的方式存到a数组里
        else if(c=='.')
        {
            i++;
            a[i]=now;
            now=0;
        }

如果碰到运算符则把最上面两数进行相应的运算

然后把值存到前一个数的位置上

        else if(c=='+')//计算 
        {
            a[i-1]=a[i-1]+a[i];
            a[i]=0;
            i--;
        } 
        else if(c=='-')
        {
            a[i-1]=a[i-1]-a[i];
            a[i]=0;
            i--;
        } 
        else if(c=='*')
        {
            a[i-1]=a[i-1]*a[i];
            a[i]=0;
            i--;
        } 
        else if(c=='/')
        {
            a[i-1]=a[i-1]/a[i];
            a[i]=0;
            i--;
        } 
    }

最终留在a[1]上的就是结果

4.队列安排

 

该题若直接用数组,那么每有一个人插入,那么其插入位置后的所有人都要往后移一位,数据可能会爆

但通过观察发现,插入一个人时,除了其插入的位置,其他人的相对位置是不变的

那么就可以抽象为一个路径问题,比如原路径为a->b->d->c,在a右侧插入一个e

则路径变为a->e->b->d->c,b、d、c的顺序没变

删除掉e则变回原路径

因此用增减路径点的思路来做这个题

 


#include<bits/stdc++.h>
using namespace std;
struct w
{
    int l,r;
} ab[100005];
int main(void)
{
    int n,p,k,m;
    cin>>n;
//初始化0,1的路径,这里固定了最后一位的右边一定是0
    ab[0].l=0;
    ab[0].r=1;
    ab[1].r=0;
    ab[1].l=0;
    for(int i=2;i<=n;i++)
    {
        cin>>k>>p;
//在k的p侧增加一个i路径点
        if(p==0) 
        {
            ab[i].r=k;
            ab[i].l=ab[k].l;
            ab[k].l=i;
            ab[ab[i].l].r=i;
        }
        else
        {
            ab[i].r=ab[k].r;
            ab[i].l=k;
            ab[k].r=i;
            ab[ab[i].r].l=i;
        }
    }
//删去m个路径点 cin>>m; for(int i=0;i<m;i++) { int a; cin>>a; if(ab[a].l==0&&ab[a].r==0)continue; else { ab[ab[a].r].l=ab[a].l; ab[ab[a].l].r=ab[a].r; ab[a].l=0; ab[a].r=0; } } for (int i=ab[0].r;i!=0;i=ab[i].r)cout<<i<<' '; return 0; }
posted on 2022-11-15 09:29  prison_warden  阅读(76)  评论(0)    收藏  举报