bzoj 4717: 改装 二分+set

        md一开始被套路了浑身难受。

       首先把所有装备扔进一个set(要用好的姿势处理重复)排序。询问的时候就扫一遍set然后把区间内的拿出来,这样就是有序的了。然后二分答案,每个船做一次二分查找,得到<=ans的有多少就好了。

       由于set重复的缘故WA了好几发,浑身难受。

AC代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
#define N 100005
using namespace std;

int n,m,cnt,a[N],b[N],q[N];
struct cmp{ bool operator()(int x,int y){ return b[x]<b[y] || b[x]==b[y] && x<y; } };
set<int,cmp> S; set<int,cmp>:: iterator it;
int read(){
	int x=0; char cr=getchar();
	while (cr<'0' || cr>'9') cr=getchar();
	while (cr>='0' && cr<='9'){ x=x*10+cr-'0'; cr=getchar(); }
	return x;
}
int work(int x){
	int l=0,r=cnt,mid;
	while (l<r){
		mid=l+r+1>>1;
		if (q[mid]<=x) l=mid; else r=mid-1;
	}
	return l;
}
int main(){
	n=read(); m=read();
	int i,j,k,x,y,z;
	for (i=1; i<=n; i++) a[i]=read();
	for (i=1; i<=m; i++){
		b[i]=read(); S.insert(i);
	}
	int cas=read(),l,r,mid,tmp;
	while (cas--){
		j=read();
		if (j){
			j=read(); k=read(); x=read(); y=read(); z=(k-j+1)*(y-x+1)-read()+1;
			for (it=S.begin(),cnt=0; it!=S.end(); it++)
				if ((*it)>=x && (*it)<=y) q[++cnt]=b[*it];
			l=0; r=2000000000;
			while (l<r){
				mid=l+(r-l>>1); tmp=0;
				for (i=j; i<=k; i++) tmp+=work(mid/a[i]);
				if (tmp>=z) r=mid; else l=mid+1;
			}
			printf("%d\n",l);
		} else{
			k=read(); x=read();
			if (!k) a[x]=read(); else{
				S.erase(x); b[x]=read(); S.insert(x);
			}
		}
	}
	return 0;
}


by lych

2016.11.12

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值