noip 2018 模拟赛10

T 1 T_1 T1——block(3829)

Description:

有一排 n n n个积木,每个的高度为 h i h_i hi,现在有水从 0 0 0开始每秒上涨 1 1 1单位,
m m m次询问,每次询问 s s s秒时,积木没被淹没的连通块个数。
n , m ≤ 500000 , h i ≤ 1 0 9 , s i ≤ s j ( i ≤ j ) n,m\le 500000,h_i\le10^9,s_i\le s_j(i\le j) n,m500000,hi109,sisj(ij)

Solution:

  • 对于询问的时间是单调增的,那么我们就可以先将积木排序,
  • 对于每次询问,看这次被淹没的积木中,每个的相邻积木是否也被淹没,
  • 从而分类讨论计算贡献即可。
  • 复杂度是线性的 Θ ( n ) \Theta(n) Θ(n)

Code:

#include<bits/stdc++.h>
using namespace std;
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;++i)
template<class T>inline void Rd(T &x){
	x=0;char c;
	while((c=getchar())<48);
	do x=(x<<1)+(x<<3)+(c^48);
	while((c=getchar())>47);
}

const int N=5e5+2;

int n,m;
int A[N];

struct p60{
	void solve(){
		while(m--){
			int s;Rd(s);
			int ans=0;
			for(int i=1;i<=n;++i){
				int j=i;
				while(A[j]>s && j<=n)++j;
				if(j>i)ans++;
				i=j;
			}
			printf("%d\n",ans);
		}
	}
}p1;

struct p100{
	
	struct node{
		int h,id;
		bool operator<(const node &_)const{
			return h<_.h;
		}
	}B[N];
	bool mark[N];
	
	void solve(){
		REP(i,1,n) B[i]=(node){A[i],i},mark[i]=1;
		sort(B+1,B+1+n);
		int ans=1,now=1;
		while(m--){
			int s;Rd(s);
			while(now<=n and B[now].h<=s){
				int x=B[now].id;
				if(mark[x-1] and mark[x+1]) ++ans;
				if(!mark[x-1] and !mark[x+1]) --ans;
				mark[x]=0;
				now++;
			}
			printf("%d\n",ans);
		}
	}
}p2;

int main(){
//	freopen("block.in","r",stdin);
//	freopen("block.out","w",stdout);
	Rd(n),Rd(m);
	REP(i,1,n) Rd(A[i]);
	
	if(n<=5000 && m<=5000)p1.solve();
	else p2.solve();
	
	return 0;
}

T 2 T_2 T2——dining

Description:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值