zzu 2024寒假训练day1(A-I)

题目链接

目录

1.A

2.B

3.C.

4.D

5.E

6.F

7.G

8.H

9.I


1.A

用数组的话,查找k和删除操作中查找x都是logn的操作,会超时,因此使用链表比较方便,用pos数组储存迭代器可弥补list不能随机访问的缺陷(复杂的题还是用静态链表吧).

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
list<int>::iterator pos[maxn];
bool erased[maxn];
int main()
{
    int n;
    cin>>n;
    list<int>quelist;
    quelist.insert(quelist.begin(),1);
    pos[1]=quelist.begin();
    int k,p;
    for(int i=2;i<=n;i++)
    {
        cin>>k>>p;
        if(p==0)
        {
            pos[i]=quelist.insert(pos[k],i);
        }
        else
        {
            auto nextiter=next(pos[k]);
            pos[i]=quelist.insert(nextiter,i);
        }
    }
    int m,x;
    cin>>m;
    while(m--)
    {
        cin>>x;
        if(!erased[x])
        {
            quelist.erase(pos[x]);
            erased[x]=true;
        }
    }
    for(int&x:quelist)
    cout<<x<<" ";
    return 0;
}

2.B

经典的栈问题 用num=num*10+s[i]求出操作数,再入栈,碰到运算符号,则取栈中的两个数运算,再将运算结果入栈.

//后缀表达式 遇到数字入栈 遇到符号取栈顶再入栈
#include<bits/stdc++.h>
using namespace std;
int main()
{
    string s;
    cin>>s;
    stack<int>st;
    int i=0;
    int num=0;
    for(int i=0;i<s.size();i++)
    {
        if(s[i]=='@')
        {
            continue;
        }
        else if(s[i]=='.')
        {
          st.push(num);
          //cout<<"num=="<<num<<"\n";
          num=0;
        }
        else if(s[i]<='9'&&s[i]>='0')
        {
            num=num*10+(s[i]-'0');
        }
        else
        {
            if(s[i]=='+')
            {
                int temp1=st.top();
                st.pop();
                int temp2=st.top();
                st.pop();
                st.push(temp1+temp2);
            }
            else if(s[i]=='-')
            {
               int temp1=st.top();
                st.pop();
                int temp2=st.top();
                st.pop();
                st.push(temp2-temp1);
            }
            else if(s[i]=='*')
            {
              int temp1=st.top();
                st.pop();
                int temp2=st.top();
                st.pop();
                st.push(temp1*temp2);
            }
            else if(s[i]=='/')
            {
                int temp1=st.top();
                st.pop();
                int temp2=st.top();
                st.pop();
                st.push(temp2/temp1);
            }
        }
    }
    cout<<st.top();
}

3.C.

用队列储存单词库,只是队列的大小有限制(虽然我用的是双端队列,但效果一样)

//机器翻译(队列题)
#include<bits/stdc++.h>
using namespace std;
bool book[1005];
int main()
{
    deque<int>que;
    int n,m;
    cin>>n>>m;
    int ans=0;
    for(int i=0;i<m;i++)
    {
        int t;
        cin>>t;
        if(!book[t])
        {
            if(que.size()==n)
            {
                int tmp=que.front();
                book[tmp]=false;
                que.pop_front();
            }
            que.push_back(t);
            book[t]=true;
            ans++;
        }
    }
    cout<<ans<<"\n";
}

4.D

用小根堆储存种数,贪心思路是:取最小值和次小值合成一堆,再重复一样的动作

//小根堆 贪心
#include<bits/stdc++.h>
using namespace std;
int main()
{
    priority_queue<int,vector<int>,greater<int>>h;
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        int t;
        cin>>t;
        h.push(t);
    }
    int ans=0;
    for(int i=0;i<n-1;i++)
    {
        int temp1=h.top();
        h.pop();
        int temp2=h.top();
        h.pop();
        h.push(temp1+temp2);
        ans+=temp1+temp2;
    }
    cout<<ans<<"\n";
    return 0;
}

5.E

就是map的使用

//哈希表  map
#include<bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    map<string,int>mp;
    int n;
    cin>>n;
    int op,t;
    string s;
    for(int i=0;i<n;i++)
    {
        cin>>op;
        if(op==1)
        {
            cin>>s>>t;
            mp[s]=t;
            cout<<"OK"<<"\n";
        }
        else if(op==2)
        {
            cin>>s;
            if(mp.find(s)==mp.end())
            cout<<"Not found"<<"\n";
            else
            cout<<mp[s]<<"\n";
        }
        else if(op==3)
        {
            cin>>s;
            if(mp.find(s)==mp.end())
            cout<<"Not found"<<"\n";
            else
            {
              mp.erase(s);
              cout<<"Deleted successfully"<<"\n";
            }
        }
        else if(op==4)
        cout<<mp.size()<<"\n";
    }
    return 0;
}

6.F

用map记录每个数的个数,在遍历每个数字 当前数字为A,就要找A-C有多少个(因为B=A-C)

//哈希 双指针 排序
#include<bits/stdc++.h>
using namespace std;
#define int long long 
signed main()
{
    int n,c;
    cin>>n>>c;
    map<int,int>mp;
    vector<int>v(n);
    for(int i=0;i<n;i++)
    {
        cin>>v[i];
        mp[v[i]]++;
    }
    int ans=0;
    for(int i=0;i<n;i++)
    {
        if(mp.find(v[i]-c)!=mp.end())
        ans+=mp[v[i]-c];
    }
    cout<<ans<<"\n";
    return 0;
}

7.G

用set记录发送过的消息,用string的find方法判断一个字符串是否含有"bie"

#include<bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    set<string>se;
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        int m;
        cin>>m;
        int cnt=0;
        for(int i=0;i<m;i++)
        {
            string s;
            cin>>s;
            if(s.find("bie")!=string::npos)
            {
                if(se.find(s)==se.end())
                {
                    se.insert(s);
                    cnt++;
                    cout<<s<<"\n";
                }
            }
        }
        if(cnt==0)
        {
            cout<<"Time to play Genshin Impact, Teacher Rice!"<<"\n";
        }
    }
    return 0;
}

8.H

遇左端点入栈,遇右端点与栈顶元素结合并将差值插入小根堆,c插入大根堆,用小的区间消化的大的c

#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
    stack<int>left;
    map<int,char>umap;
    priority_queue<int>c;//大根堆
    priority_queue<int,vector<int>,greater<int>>minus;//小根堆
    for(int i=0;i<n;i++)
    {
       int l;
       cin>>l;
       umap[l]='l';
    }
    for(int i=0;i<n;i++)
    {
      int r;
      cin>>r;
      umap[r]='r';
    }
    for(int i=0;i<n;i++)
    {
       int t;
	   cin>>t;
	   c.push(t); 
    }
    for(auto i:umap)
    {
        if(i.second=='l')
           left.push(i.first);
        else
            {
			if(!left.empty())
            {
                minus.push(i.first-left.top());
                left.pop();
            }
            }
    }
    int sum=0;
    for(int i=0;i<n;i++)
    {
      sum+=minus.top()*c.top();//小区间消化大的c
      minus.pop();
      c.pop();
    }
    cout<<sum<<"\n";
}
}

9.I

链表题

重点是找出死掉的怪物和死掉怪物左右的新邻居

1.数据的输入,链表的初始化连接

2.找出没一轮的怪物候选人(第一轮过后死的怪物的左右即为候选人,用set储存)

3.筛选新一轮的候选人,并重连链表,去除死掉的怪物

//输入攻击和输出 处理好pre和nxt a[0]=0 d[0]=2e9+5 nxt[n]=0 pre[1]=0
//set 候选怪物入列 死了的怪物的左右需要重判
//判断是否死亡
#include<bits/stdc++.h>
using namespace std;
#define int long long 
const int maxn=3e5+5;
int a[maxn],d[maxn],pre[maxn],nxt[maxn];
int d1[maxn];//死亡的小鼠
bool died[maxn];//判断是否死亡
signed main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int t;
    cin>>t;
    while(t--)
    {
        memset(died,false,sizeof(died));
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        for(int i=1;i<=n;i++)
            cin>>d[i];
        
        a[0]=0;d[0]=2e9+5;
        nxt[n]=0;
        
        for(int i=1;i<=n;i++)
        {
            pre[i]=i-1;
            nxt[i-1]=i;
        }

        set<int>se;
        int cnt=0;
        for(int i=1;i<=n;i++)
        {
            se.insert(i);//第一批候选者
        }

        for(int i=1;i<=n;i++)//n轮
        {
            for(auto idx:se)
            {
                if(died[idx])continue;
                if(a[pre[idx]]+a[nxt[idx]]>d[idx])
                {
                    d1[++cnt]=idx;
                }
            }
            se.clear();
            for(int i=1,idx;i<=cnt;i++)
            {
                idx=d1[i];
                se.insert(pre[idx]);
                se.insert(nxt[idx]);
                nxt[pre[idx]]=nxt[idx];//链表连接
                pre[nxt[idx]]=pre[idx];
                died[idx]=true;
            }
            cout<<cnt<<" ";
            cnt=0;
        }
        cout<<"\n";
    }
    return 0;
}

  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值