STL(暑期训练1)

栈stack

stack<int>ss;
a=ss.top();//返回栈顶的元素
ss.pop();//从栈中取出并删除元素
ss.size();//返回栈中元素个数
ss.push(e);//向栈中添加元素e
ss.empty()://栈为空时返回true

队列queue

queue<int>q;
q.push(x);
a=q.front();
q.pop();
q.empty();

优先队列priority_queue

priority_queue<int,vector<int>,less<int>>q1;//从大到小
priority_queue<int,vector<int>,greater<int>>q2;//从小到大

例1--Buy and Resell

题意:

有n个城市,第i天你会达到第i个城市,在第i个城市中,你可以用ai元购买一个物品,或者用ai元卖掉一个物品,你可以同时保存多个物品。最开始你身上没有物品,但是又无限的金钱,现在要求你从城市1走到城市n,问你最大的收益是多少。

思路:

我们使用优先队列存储我们会考虑进行贸易的城市的价格,优先级为由小到大。
当我们在某个城市选择以a价格买入b价格卖出时,我们向队列里加入两个b,并且把b-a算入利润中。

那么如果在之后的操作中,我们想以a买入以c卖出,我们的实际操作是:

买入队列中的b以c卖出,这时我们的收益是c-b+b-a=c-a,而且还有一个b在队列中。

对于整个模拟过程中,当我们买入的物品为不是之前加入队列的物品则贸易次数+2,否则不交易。

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
typedef long long ll;
priority_queue< int,vector<int>,greater<int> > buy,sell;
ll a[maxn];
int main()
{
	int n,t;
	cin>>t;
	while(t--)
    {
		cin>>n;
		for(int i=0;i<n;i++)
	 	   cin>>a[i];
		ll ans=0,cnt=0;
		for(int i=0;i<n;i++)
        {
			if(buy.size()!=0&&sell.size()!=0&&buy.top()<sell.top()&&sell.top()<a[i])
			{
				ans+=a[i];
				cnt++;
				sell.push(a[i]);
				buy.pop();
			}
			else if(sell.size()!=0&&sell.top()<a[i])
			{
				buy.push(sell.top());
				sell.pop();
				sell.push(a[i]);
				ans+=a[i]-2*buy.top();
			}
			else if(buy.size()!=0&&buy.top()<a[i])
			{
				ans+=a[i];
				cnt++;
				sell.push(a[i]);
				buy.pop();
			}
			else
            {
              buy.push(a[i]),ans-=a[i];
            }
	 	}
	 	while(!buy.empty())
	 	{
	 		ans+=buy.top();
	 		buy.pop();
        }
        cout<<ans<<" "<<2*cnt<<endl;
		while(!buy.empty())
		{
		    buy.pop();
		}
		while(!sell.empty())
        {
            sell.pop();
        }

	 }
}

例2--CF1353D

题意:

给定一个长为n的空数组,将1~n的数字放到数组之中。

放置规则:

  1. 选择长度最长的空白元素区间,如果有多个,选择最靠左的区间;
  2. 将 i 放置在 (l+r)/2 的位置;

输出最后的数组。

思路:

拿数字找位置(二分+优先队列)

将空元素区间存储在优先队列之中并设计排序

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int a[N];
struct node
{
    int l,r;
    friend bool operator < (node a,node b)
    {
        if(abs(a.r-a.l)==abs(b.r-b.l))
        {
            return a.l>b.l;
        }
        else
        {
            return abs(a.r-a.l)<abs(b.r-b.l);
        }
    }
};
int main()
{
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        memset(a,0,sizeof(a));
        priority_queue<node>q;
        if(n==1)
        {
            printf("1\n");
        }
        else
        {
            q.push({1,n});
            int k=1;
            while(!q.empty())
            {
                node tmp=q.top();
                q.pop();
                int l=tmp.l;
                int r=tmp.r;
                int mid;
                if((r-l+1)%2==0)
                    mid=(r+l-1)/2;
                else
                    mid=(l+r)/2;
                a[mid]=k;
                k++;
                if((mid-1)>0&&l<(mid-1))
                {
                    q.push({l,mid-1});
                }

                if(mid<n&&(mid+1)<r)
                {
                    q.push({mid+1,r});
                }
            }
            for(int i=1;i<=n;i++)
            {
               if(a[i]==0)cout<<k++<<" ";
               else cout<<a[i]<<" ";
            }
            cout<<endl;
        }
    }
}

双向队列 deque

q.push_front(val);q.pop_front();
q.push_back(val);q.pop_back();

deque模板题

vector数组

1.vector<int> v;
2.v.push_back(1);
3.v.pop_back();//删除尾部元素
4.v.insert(v.begin() + i, a); //在第i + 1个元素前面插入a;
5.v.erase(v.begin() + 2); //删除第3个元素
6.v.erase(v.begin() + i, v.end() + j); //删除区间[i, j - 1]; 区间从0开始
7.v.size();
8.v.clear();
9.reverse(v.begin(), v.end()); //将元素翻转,即逆序排列!
10.sort(v.begin(), v.end()); //(默认是按升序排列, 即从小到大).

multiset

set和multiset会根据特定的排序准则,自动将元素进行排序。不同的是multiset允许元素重复。

(1)定义multiset<int> ms
(2)插入元素k  ms.insert(k)  
(3)ms.count(k) 元素k在容器内出现的次数(为0表示不在容器中)
(4)ms.erase(k)  删除容器中所有元素k
(5)ms.clear()  清空容器
(6)ms.size()  容器元素个数
(7)ms.empty() 容器是否为空
(8)定义正向迭代器  multiset<int>::iterator it ;
 ms.find(k) 寻找k,若找到返回第一个k对应的迭代器,否则返回it.end();
ms.erase(it) 删除迭代器it对应的元素
ms.erase(l, r)   删除迭代器[l, r)之间的元素
lower_bound(k)返回第一个大于等于k的元素的迭代器
upper_bound(k) 返回第一个大于k元素的迭代器

例--Bombing

题意:

现在,在一个1e9×1e9的平面图上有n座城市(n<=100000),系统已经为你提供了它们的坐标。
你有m架轰炸机,每架轰炸机上都携带着病毒炸弹。而每一架轰炸机的飞行模式为c d。

    当c=0时,轰炸机将会朝着x=d的方向轰炸城市;
    当c=1时,轰炸机将会朝着y=d的方向轰炸城市。

现在你想知道你的每一架轰炸机摧毁了多少城市。
(当城市A被摧毁时,城市A不能再被记入后面的轰炸机战绩之中)
思路:

map<int,multiset<int> > mx,my;
 
mx[x坐标]=>{y1,y2,y3...}  落在x坐标上的y坐标集合
 
my[y坐标]=>{x1,x2,x3...}  落在y坐标上的x坐标集合

AC代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<map>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF&&n&&m)
    {
        int x,y,c,d;
        map<int,multiset<int> >ax,ay;
        for(int i=0;i<n;i++)
        {
           scanf("%d%d",&x,&y);
           ax[x].insert(y);
           ay[y].insert(x);
        }
       for(int i=1;i<=m;i++)
       {
           scanf("%d%d",&c,&d);
           if(c==1)//y=?横着的
           {
               printf("%d\n",ay[d].size());
               multiset<int>::iterator it;
               for(it=ay[d].begin();it!=ay[d].end();it++)
               {
                   ax[*it].erase(d);
               }
               ay[d].clear();
           }
           else if(c==0)//x=?竖着的
           {
               printf("%d\n",ax[d].size());
               multiset<int>::iterator it;
               for(it=ax[d].begin();it!=ax[d].end();it++)
               {
                   ay[*it].erase(d);
               }
               ax[d].clear();
           }
       }
       printf("\n");
    }
}

MAP

1.第一个关键字(key),只能在map中出现一次。

   第二个关键字的值(value)

map<int,string>mp;

2. 插入数据

 (1)mp.insert(pair<int, string>(1, "one"));
 (2)cin>>a>>b;mp[a]=b;

3.map遍历

 map<int, string>::iterator it;
 for(it=mp.begin();it!=mp.end();it++)
 {
    int a=it->first;
    string b=it->second;
 }

 4.当所查找的关键key出现时,它返回数据所在对象的位置,如果沒有,返回iter与end函数的值相同。

// find 返回迭代器指向当前查找元素的位置否则返回map::end()位置
it = mp.find("123");

 MAP例题

二分查找函数

1、binary_search(beg,end,val)

返回一个bool变量,以二分法在[beg,end]之间查找val,找到返回true,找不到返回false。

2、lower_bound(beg,end,val)

返回一个迭代器,指向非递减序列[first, last)中的第一个大于等于(>=)val的位置。

3、upper_bound(beg,end,val)

返回一个迭代器,指向非递减序列[first, last)中的第一个大于 (>) val的位置。

next_permutation全排列函数

int num[3]={1,2,3};  
    do  
    {  
        cout<<num[0]<<" "<<num[1]<<" "<<num[2]<<endl;  
    }while(next_permutation(num,num+3));  

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值