开始: 2022-06-11 19:00:00

2022年6月双周赛(高级班)

结束: 2022-06-11 21:30:00
当前: 2025-0606-0202 01:20:22  类型:OI 状态:已经结束 

//B. 木材仓库
//C++中set用法详解:https://blog.csdn.net/byn12345/article/details/79523516

#include<bits/stdc++.h>
using namespace std;
set<int> s;//使用STL中的set来解题
void Insert(int x)
{
//set的操作之一:find
//s.find(x),返回给定值的定位器,如果没找到则返回s.end()。
if(s.find(x)!=s.end())//返回的是一个定位器而不是s.end(),证明set中已经有x
cout<<"Already Exist\n";
//set的操作之二:insert
else s.insert(x); //如果set中没有x,则插入
}
void Delete(int x)
{
//set的操作之三:empty
if(s.empty()) cout<<"Empty\n";
else
{
set<int>::iterator it,las,nex;//定义指向set内元素的指针,las表示前驱,nex表示后继
it=s.find(x);//查找set中有没有x这个元素
if(it!=s.end())//证明有这个元素
{
cout<<*it<<endl;
s.erase(it);
}
else //没有这个元素
{
//set的操作之四:s.lower_bound(x) 返回第一个大于等于 x 的位置
nex=las=s.lower_bound(x);
if(nex==s.begin())//如果第一个大于x的数已经是set中最小的数,那么直接输出
{
cout<<*nex<<endl;
//set的操作之五:erase(it),即删除it指针内指向的值
s.erase(nex);
}
else if(nex==s.end())//表明没有大于x的数
{
las--;//由于set中的数有序,第一个小于x的数一定是set中的最后一个数
cout<<*las<<endl;
s.erase(las);
}
else
{
las--;//找第一个小于x的数
if(*nex-x<x-*las)//如果第一个大于x的数距x的距离小于第一个小于x的数
{
cout<<*nex<<endl;
s.erase(nex);
}
else
{
cout<<*las<<endl;
s.erase(las);
}
}

}
}
}
int main()
{
int n;
cin>>n;
while(n--)
{
int opt,length;
cin>>opt>>length;
if(opt==1) Insert(length);
else Delete(length);
}
return 0;
}

 

//C. 参加比赛

#include<bits/stdc++.h>
using namespace std;
int n,last,ans;
struct node
{
int s,t;
}a[1000010];
bool cmp(node a,node b)
{
return a.t<b.t;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&a[i].s,&a[i].t);
sort(a+1,a+n+1,cmp);
last=a[1].t; //先选择第一个区间
ans=1;
for(int i=2;i<=n;i++)
{
if(a[i].s>=last)//如果开始时间在上一次比赛的结束时间之后
{
last=a[i].t;
ans++;
}
}
printf("%d",ans);
return 0;
}
/*
思路:一道经典的贪心题
先将每一场比赛以结束时间从小到大排一次序,得到一个有序的结构体数组
首先,一定要选择第一个区间,因为排在它之后的比赛结束时间一定大于等于它,挤占后面比赛的时间只可能比它更多
所以,贪心的选择第一个区间是一个局部最优解
然后,找到之后第一个不与第一个比赛时间相交的比赛,选择它,可以证明,这也是局部最优解
依次类推,最终选的比赛数量必然是最多的
*/

 

//D. 木板与数

//具体题解见视频

#include<bits/stdc++.h>
using namespace std;
int n,k;
int a[2100000];
int main()
{
//单调队列
deque<int> q;
cin>>n>>k;
for(int i=1; i<=n; i++)
{
//维护一个单调递增的队列
scanf("%d",&a[i]);
if(i-q.front()>=k) q.pop_front();//如果队首已经过期了 出队
while(!q.empty()&&a[i]>=a[q.back()]) q.pop_back();//如果队尾元素比当前元素小或相等 队尾出队
q.push_back(i);
if(i>=k) printf("%d\n",a[q.front()]);
}
return 0;
}
/*
1: q: 1
2: q: 2
3: q: 2 3 输出a[2]
4: q: 2 4 输出a[2]
5: q: 4 2 输出a[4]
*/