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