2023暑假第一次训练

目录

队列安排(双向链表)

表达式求值(栈/思维)

求m区间内的最小值(单调队列)

滑动窗口 /【模板】单调队列

机器翻译 (队列)

小组队列(队列)

切蛋糕(单调队列)


队列安排(双向链表)

 题目链接:洛谷 P1160 队列安排

思路

1.首先,先建一个结构体,分left和right,然后一开始只有1号,要设一个边界,表的最左边是0,最右边是100010(因为数据大不过100010)。

2.接着对于每次插入,有左和右种情况,如A,C中插入B,就要改A的right,将A.right的C改为B,就要改C.left的A改为B,那新来的B呢?它的左右邻居就要赋值(B.left=A,B.right=C)。

3.对于每次删除,就要更新被删除者的左右两边数据,如A,B,C删除B,就要改B.left的右边(A.right)为C,就要改B.right的左边(C.left)为A。

4.最后输出时先从bib.right开始判断(一开始bib为0),如果bib.right是有数据的,那么就输出并把下一个的bib跟新为bib.right以准备判断。如果bib.right是100010,也就是边界,说明没有后路了就退出。

数组:

// Problem: P1160 队列安排
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1160
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<map>

using namespace std;

typedef long long ll;

const int N = 200010;


int l[N],r[N];
bool st[N];
int n,m;

void init(){
	r[0]=1;
	l[1]=0;
	r[0]=1;
}
    
void add_left(int k,int x){
	r[l[k]]=x;
	l[x]=l[k];
	r[x]=k;
	l[k]=x;
}

void add_right(int k,int x){
	l[r[k]]=x;
	r[x]=r[k];
	l[x]=k;
	r[k]=x;
}

void s(){
    cin>>n;
   
    init(); 
    memset(st,false,N);
    
    for(int i=2;i<=n;i++){
    	int k,op;
        cin>>k>>op;
        if(op==0){
            add_left(k,i);
        }
        else{ 
           add_right(k,i);
        }
    }
   
    cin>>m;
    for(int i=1;i<=m;i++){
    	int p;
        cin>>p;
        st[p]=1; 
    }
    for(int i=r[0];1;i=r[i]){
        if(st[i]==0) cout<<i<<' ';
        if(r[i]==0) break;
    }
} 

int main(){
	int T=1;
	//cin>>T;
	while(T--){
		s();
	}
	return 0;
	
}

list容器 

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

const int N = 2e5+5;

int main(){
	int n,m;
	cin>>n;
	
	vector<list<int>::iterator> v(n);
	
	list<int> lis;
	lis.push_front(0);
	v[0]=lis.begin();
	
	for(int i=1;i<n;i++){
		int k,p;
		cin>>k>>p;
		k--;
		if(p==1){
			auto nxt=next(v[k]);
			v[i]=lis.insert(nxt,i);  //在next位置插i元素,之后的向后移
		}
		else{
			v[i]=lis.insert(v[k],i);
		}
	}
	
	cin>>m;
	vector<bool> ve(n);
	while(m--){
		int x;
		cin>>x;
		x--;
		if(ve[x]){
			continue;
		}
		ve[x]=true;
		lis.erase(v[x]);
	}
	for(int x:lis){
		cout<<x+1<<" "[x==lis.back()];
	}
	
	return 0;	

}

表达式求值(栈/思维)

题目链接:洛谷 表达式求值

代码

// Problem: P1981 [NOIP2013 普及组] 表达式求值
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1981
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

const int N = 2e5+5;
const int mod=10000;

int main(){
	stack<int> x; //先进后出
	int a,b;
	char c;
	cin>>a;
	a%=mod;  //不加会wa
	x.push(a);
	while(cin>>c>>b){
		if(c=='*'){
			int t=x.top();
			x.pop();  //此时对头为a,所以要删除,以便后面再多加一遍
			x.push(t*b%mod);
		}
		else{
			x.push(b);  //队头会变成b
		}
	}
	int res=0;
	while(x.size()){
		res+=x.top();
		res%=mod;
		x.pop();
	}
	cout<<res<<"\n";
	
	return 0;
}

求m区间内的最小值(单调队列)

题目链接:洛谷 求m区间内的最小值

数组:

// Problem: P1440 求m区间内的最小值
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1440
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>

using namespace std;

typedef long long ll;

const int N = 2000010;

int a[N],q[N];

int main(){
	int n,m;
    cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	cout<<0<<"\n";
	int hh=0,tt=-1;
	for(int i=1;i<n;i++){  //ai之前m个数,不算ai
		if(hh<=tt&&i-q[hh]+1>m){
			hh++;   //队头出队
		}
		while(hh<=tt&&a[i]<=a[q[tt]]){
			tt--;  //后面的数小于队尾,队尾出队
		}
		q[++tt]=i;
		cout<<a[q[hh]]<<"\n";
	}

    return 0;
	
}

deque

// Problem: P1440 求m区间内的最小值
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1440
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<cstdio>
#include<deque>

using namespace std;

const int N=2e6+6;

int n,m;
int a[N],ans[N];
deque<int> de;

int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		while(de.size()!=0&&de.front()<i-m){
			de.pop_front();
		}
		if(de.size()==0)  printf("0\n");
		else  printf("%d\n",a[de.front()]);
		while(de.size()!=0&&a[de.back()]>=a[i]) {
			de.pop_back();
		}
		de.push_back(i);
	}
	return 0;
}

滑动窗口 /【模板】单调队列

 题目链接:洛谷 滑动窗口

数组

// Problem: P1440 求m区间内的最小值
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1440
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>

using namespace std;

typedef long long ll;

const int N = 2000010;

int a[N],q[N];

int main(){
	int n,m;
    cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	
	int hh=0,tt=-1;
	for(int i=1;i<=n;i++){  
		if(hh<=tt&&i-q[hh]+1>m){
			hh++;   
		}
		while(hh<=tt&&a[i]<=a[q[tt]]){
			tt--;  
		}
		q[++tt]=i;
		if(i>=m) cout<<a[q[hh]]<<' ';
	}
	cout<<"\n";
	
	hh=0,tt=-1;
	for(int i=1;i<=n;i++){
		if(hh<=tt&&i-q[hh]+1>m){
			hh++;
		}
		while(hh<=tt&&a[i]>=a[q[tt]]){
			tt--;
		}
		q[++tt]=i;
		if(i>=m) cout<<a[q[hh]]<<' ';
	}
	cout<<"\n";
	
    return 0;
    
}

deque 

#include <bits/stdc++.h>
using namespace std;
 
const int N = 1000010;

int main(){
    int n, k;
    int a[N];
    cin >> n >> k;
    for (int i = 1; i <= n; i ++ ) {
        cin >> a[i];
    }
    deque<int> q;
    for(int i = 1; i <= n; i++) {
        while(q.size() && q.back() > a[i]) 
            q.pop_back();
        q.push_back(a[i]);
        if(i - k >= 1 && q.front() == a[i - k]) 
            q.pop_front();
        if(i >= k)
            cout << q.front() <<" ";
    }
    q.clear();
    cout << endl;
 
    for(int i = 1; i <= n; i++) {
        while(q.size() && q.back() < a[i]) q.pop_back();
        q.push_back(a[i]);
        if(i - k >= 1 && a[i - k] == q.front()) q.pop_front(); 
        if(i >= k) cout << q.front() << " ";
 
    }
    
    return 0;
    
}

机器翻译 (队列)

题目链接:洛谷 机器翻译

// Problem: P1540 [NOIP2010 提高组] 机器翻译
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1540
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>

using namespace std;

typedef long long ll;

const int N = 200010;

bool st[N];

int main(){
	int m,n;
	cin>>m>>n;
	memset(st,false,N);
	
	int a[N];
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	ll res=0;
	
	queue<int> q;
	for(int i=0;i<m;i++){
		if(!st[a[i]]){
			q.push(a[i]);
			st[a[i]]=1;
			res++;
		}
	}
	for(int i=m;i<n;i++){
		if(q.size()>m){
			st[q.front()]=0;
			q.pop();
		}
		if(!st[a[i]]){
			q.push(a[i]);
			st[a[i]]=1;
			res++;
		}
	}
	cout<<res<<"\n";

    return 0;

}

小组队列(队列)

题目链接:洛谷 小组队列

// Problem: P2776 [SDOI2007] 小组队列
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2776
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<queue>

using namespace std;

typedef long long ll;

const int N = 200010;

int main(){
	int n,m;
	cin>>n>>m;
	int a[N];
	queue<int> zu,q[301];
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	
	int t;
	cin>>t;
	while(t--){
		string op;
		cin>>op;
		if(op=="push"){
			int x;
			cin>>x;
			if(q[a[x]].empty()){  //q数组里面的
				zu.push(a[x]);
			}
			q[a[x]].push(x);   //a[x]后面加上x
		}
		else{
			cout<<q[zu.front()].front()<<"\n"; //
			q[zu.front()].pop();  //移除
			if(q[zu.front()].empty()){
				zu.pop();
			}
		}
	}

    return 0;
	
}

题目链接:洛谷 堆

// Problem: P3378 【模板】堆
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3378
// Memory Limit: 512 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

typedef long long ll;

const int N = 2000010;

int h[N],ph[N],hp[N],cnt;

void heap_swap(int a,int b){
	swap(ph[hp[a]],ph[hp[b]]);
	swap(hp[a],hp[b]);
	swap(h[a],h[b]);
}

void up(int u){
	while(u/2&&h[u]<h[u/2]){
		heap_swap(u,u/2);
		u>>=1;
	}
}

void down(int u){
	int t=u;
	if(u*2<=cnt&&h[u*2]<h[t]) t=u*2;
	if(u*2+1<=cnt&&h[u*2+1]<h[t]) t=u*2+1;
	if(u!=t){
		heap_swap(u,t);
		down(t);
	}
}

void s(){
	int n,m=0;
	cin>>n;
	while(n--){
		int op;
		cin>>op;
		if(op==1){
			ll x;
			cin>>x;
			cnt++;
			m++;
			ph[m]=cnt,hp[cnt]=m;
			h[cnt]=x;
			up(cnt);
		}
		else if(op==2){
			cout<<h[1]<<"\n";
		}
		else if(op==3){
			heap_swap(1,cnt);
			cnt--;
			down(1);
		}
	}

}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	int T=1;
	//cin>>T;
	while(T--){
	    s();
	}
	
	return 0;	

}

切蛋糕(单调队列)

题目链接:洛谷 切蛋糕

// Problem: P1714 切蛋糕
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1714
// Memory Limit: 128 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

const int N = 5e5+5;

int main(){
	int n,m;
	cin>>n>>m;
	int a[N],sum[N];
	for(int i=0;i<N;i++){
		sum[i]=0;
	}
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n;i++){
		sum[i]=sum[i-1]+a[i];
	}
	
	deque<int> de;
	de.push_back(0);
	int ans=-0x3f3f3f3f;
	for(int i=1;i<=n;i++){
		while(de.front()+m<i){
			de.pop_front();
		}
		ans=max(ans,sum[i]-sum[de.front()]);
		while(!de.empty()&&sum[de.back()]>sum[i]){
			de.pop_back();
		}
		de.push_back(i);
	}
	cout<<ans<<"\n";
	
	
	return 0;	

}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值