- 吴易繁 的博客
七月暑期集训DAY10——数据结构专题
- @ 2024-7-18 19:51:15
A. 排队
题目类型:双向队列或双链表
思路
这道题目从题目描述很明显可以看出来需要用一个双向的数据结构,那像双向队列或双链表的这种双向的数据结构就都可以用上来,只要好好学这种双向的数据结构,将模版改一下,应该都能做对。
代码
双链表
#include<bits/stdc++.h>
using namespace std;
int idx,e[100010],r[100010],l[100010],head,talt,cnt;
void init(){
head=0,talt=100010;
r[head]=talt;
l[talt]=head;
idx=1;
}
void se(int k){
r[l[k]]=r[k];
l[r[k]]=l[k];
}
void add(int k,int cnt){
e[idx]=cnt;
r[idx]=r[k];
l[idx]=k;
l[r[k]]=idx;
r[k]=idx;
idx++;
}
int main(){
freopen("pd.in","r",stdin);
freopen("pd.out","w",stdout);
init();
int n;
cin>>n;
while(n--){
char a,b;
cin>>a>>b;
int t;
if(a=='A'&&b=='L'){
cnt++;
add(head,cnt);
}
if(a=='A'&&b=='R'){
cnt++;
add(l[talt],cnt);
}
if(a=='D'&&b=='L'){
cin>>t;
while(t--) se(r[head]);
}
if(a=='D'&&b=='R'){
cin>>t;
while(t--) se(l[talt]);
}
}
for(int i=r[head];i!=talt;i=r[i]) cout<<e[i]<<endl;
return 0;
}
本题代码已AC,下一次继续保持。
B. 插入删除
题目类型:哈希表与双链表
思路
这道题目从题目描述很明显可以看出来需要用双链表,而因为要找元素k会费时间,所以要用哈希表,只要将模版改一下就行了。
代码
#include<bits/stdc++.h>
using namespace std;
unordered_map<int,int> mp;
const int N=4e5+10;
int e[N],r[N],l[N],idx;
void init(){
r[0]=1;
l[1]=0;
idx=2;
}
void add(int k,int x){
mp[x]=idx;
e[idx]=x;
l[idx]=k;
r[idx]=r[k];
l[r[k]]=idx;
r[k]=idx++;
}
void remove(int k){
r[l[k]]=r[k];
l[r[k]]=l[k];
}
int main(){
freopen("insdel.in","r",stdin);
freopen("insdel.out","w",stdout);
init();
int n;
cin>>n;
for(int i=1;i<=n;i++){
int a;
cin>>a;
if(i==1) add(0,a);
else add(idx-1,a);
}
int q;
cin>>q;
while(q--){
int b;
cin>>b;
if(b==1){
int x,y;
cin>>x>>y;
add(mp[x],y);
}
else{
int x;
cin>>x;
remove(mp[x]);
}
}
for(int i=r[0];i!=1;i=r[i]) cout<<e[i]<<" ";
return 0;
}
这道题目我在写的时候只写了双链表,没写哈希表,所以没过,下一次要将各种数据结构结合起来写。
C. 拍照
题目类型:双指针
思路
对于这道题目我们可以双指针遍历一下,若全种族都在,再压缩一下,若也可以,就继续压缩,同时更新最大值,直到不能压缩为止。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
pair<int,int> a[N];
unordered_map<int,int> b,c;
using namespace std;
signed main(){
freopen("photo.in","r",stdin);
freopen("photo.out","w",stdout);
int n,cnt=0;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].first>>a[i].second;
if(!b[a[i].second]) cnt++;
b[a[i].second]++;
}
sort(a+1,a+1+n);
int l=1,r=1,ans=0x3f3f3f3f;
while(l<=n&&r<=n){
if(c[a[r].second]==0) cnt--;
c[a[r].second]++;
if(cnt) r++;
else{
int d=a[r].first-a[l].first;
ans=min(ans,d);
if(c[a[l].second]==1) cnt++,l++;
else l++;
c[a[l-1].second]--;
}
}
cout<<ans;
return 0;
}
这道题目完全没有思路,所以就放弃了,下一次不能轻易放弃。
D. 小马要做最棒的牛
题目类型:栈或DP
思路
若用DP,则遍历每一层,若用栈,直接模拟即可。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
long long a[N],mod=12345678910,b;
int main(){
freopen("horse.in","r",stdin);
freopen("horse.out","w",stdout);
int n;
cin>>n;
for(int i=1;i<=n;i++){
int c;
cin>>c;
if(c==0) b++;
else{
if(!a[b]) a[b-1]=(a[b-1]+1)%mod,b--;
else a[b-1]=(a[b-1]+a[b]*2)%mod,a[b--]=0;
}
}
cout<<(a[0]+mod)%mod;
return 0;
}
没有时间了,所以没做这题,下次提高做题速度。
E. 小田在努力切割木板
题目类型:堆
思路
用小根堆来加入数据,每次选最小的两个数字加起来再加入小根堆即可,这不过每一次ans都要加最小的两个数字,注意:要开long long。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
priority_queue<int,vector<int>,greater<int>> q;
signed main(){
freopen("qg.in","r",stdin);
freopen("qg.out","w",stdout);
int n;
cin>>n;
int ans=0;
for(int i=1;i<=n;i++){
int a;
cin>>a;
q.push(a);
}
while(q.size()>=2){
int A=q.top();
q.pop();
int B=q.top();
q.pop();
q.push(A+B);
ans+=A+B;
}
cout<<ans;
return 0;
}
没有时间了,所以没做这题,下次要提高做题速度。