• 【USCAO2018FEB-GOLD】Snow Boat(Set/线段树/并查集/单调栈)


    描述
    冬天到来,南方也下雪了。
    石室中学铺满了积雪,从机房到食堂有一条道路。这条道路可以可以分为N段,第ii段积了aia_i厚的雪。要想去食堂吃饭,LL必须穿合适的鞋子,他在机房一共放了BB双鞋子编号1..B1..B,每双鞋子有不同的功效,具体来说对于第i双鞋子可以让LL在最多SiS_i厚的积雪中行走,且可以让L每一步最多前进DiD_i段。
    LL需要从第11段出发,走到第NN段,他可以选择哪些鞋子。
    输入
    第一行2个整数N,BN,B
    第二行是NN个整数,表示ai,a1=an=0ai,a1=an=0
    接下来是BB行,每行22个整数Si,diSi,di
    输出
    NN行,每行一个整数ansi=(0,1)ans_i=(0,1)表示是否可以选择第ii双鞋子让他走到第NN段,11表示选择,00表示不行
    样例输入 [复制]
    8 7
    0 3 8 5 6 9 0 0
    0 5
    0 6
    6 2
    8 1
    10 1
    5 3
    150 7
    样例输出 [复制]
    0
    1
    1
    0
    1
    1
    1
    提示
    第一双鞋子让L开始最多滑行道第66段,然后无法前进
    第二双鞋子让L开始最多可以滑行道第77段,然后可以到终点
    第三双鞋子可以让L先滑行道第22段,然后滑行道第44段,然后滑行道第55段,然后滑行道第77段,最后到终点
    【数据范围】
    对于100%100\%的数据:1N,B105,0ai,si109,1diN11≤N,B≤10^5 ,0≤a_i,s_i≤10^9,1≤d_i≤N−1

    简单题,考试的时候可删堆没有判sizesize就咕咕了

    做法很多,讲讲自己的吧

    可以发现把鞋子排序之后,可以走的地点一定是单调递加的

    发现答案就是所有可以走的点的距离的最大值和每一步比较一下

    每加一个点就是删去减去左右距离加上左边和该点的距离和右边和该点的距离

    SetSet维护一下就可以了

    维护最大值可以用一个可删堆

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
    	char ch=getchar();
    	int res=0,f=1;
    	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    	while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    	return res*f;
    }
    #define ll long long
    #define it set<plc>::iterator
    const int N=100005;
    int n,b,fg,top;
    int lis[N],mx,ans[N];
    struct shoe{
    	int blt,dis,id;
    }p[N];
    struct plc{
    	int dep,pos;
    	inline bool operator < (const plc &a)const{
    		return pos<a.pos;
    	}
    }a[N];
    inline bool comp(int x,int y){
    	return a[x].dep<a[y].dep;
    }
    inline bool cmp(const shoe&a,const shoe &b){
    	return a.blt<b.blt;
    }
    struct heap{
    	priority_queue<int> a,b;
    	inline void push(int x){
    		a.push(x);
    	}
    	inline void erase(int x){
    		b.push(x);
    	}
    	inline int top(){
    		while(b.size()&&a.top()==b.top())
    			a.pop(),b.pop();
    		return a.top();
    	}
    }A;
    it l,r;
    set<plc> st;
    inline it pre(it a){
    	if(a!=st.begin())a--;
    	return a;
    }
    inline it nxt(it a){
    	a++;
    	if(a==st.end())a--;
    	return a;
    }
    int main(){
    	n=read(),b=read();
    	A.push(n-1);
    	for(int i=1;i<=n;i++)
    		lis[i]=i,a[i].dep=read(),a[i].pos=i;
    	for(int i=1;i<=b;i++){
    		p[i].blt=read(),p[i].dis=read(),p[i].id=i;
    	}
    	sort(lis+1,lis+n+1,comp);
    	for(int i=1;i<=n;i++){
    		if(lis[i]==1){swap(lis[1],lis[i]);break;}
    	}
    	for(int i=1;i<=n;i++){
    		if(lis[i]==n){swap(lis[2],lis[i]);break;}
    	}
    	sort(p+1,p+b+1,cmp);top=1;
    	for(int i=1;i<=b;i++){
    		while(top<=n&&a[lis[top]].dep<=p[i].blt){
    			int k=lis[top];
    			st.insert(a[k]);
    			if(k==1||k==n){
    				top++;continue;
    			}
    			l=r=st.find(a[k]);
    			l=pre(l),r=nxt(r);
    			A.erase((*r).pos-(*l).pos);
    			A.push((a[k].pos-(*l).pos));
    			A.push(((*r).pos-a[k].pos));
    			top++;
    		}
    		ans[p[i].id]=(A.top()<=p[i].dis);
    	}
    	for(int i=1;i<=b;i++)cout<<ans[i]<<'
    ';
    }
    
  • 相关阅读:
    Linux文件名匹配
    Linux的常用命令
    百度飞桨学习笔记【Windows下用anaconda安装飞桨】
    在python中调用shell命令获得返回值
    使用sratoolkit下载NCBI数据
    perl 打开gz压缩文件 输出gz压缩文件
    jupyter notebook安装教程,打开ipynb文件
    生物信息学相关网站和博客资源
    R的循环补齐功能
    perl 遍历目录并且对目录中的文件进行操作
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366333.html
Copyright © 2020-2023  润新知