目录
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;
}