题目描述
小敏和小燕是一对好朋友。
他们正在玩一种神奇的游戏,叫Minecraft。
他们正在盖建筑,他们手上有不同的方块。
每种方块有不同的不美观度,他们持有每种方块的数量也不一样。
他们现在准备实行他们众多建筑计划中的一个。
他们的建筑计划有不同的要求,不美观度有上限和下限。为了方便拿取方块,他们也要求所用的方块在方块堆中的连续一段。每个建筑计划需要固定的方块数。
他们现在要知道,在最好情况下,每个建筑计划中最不美观的方块的不美观度是多少。
数据范围
对于30%的数据,n<=10,m<=30
对于40%的数据,n<=100,m<=300
对于60%的数据,n<=1000,m<=3000
对于100%的数据,n<=30000,m<=30000
样例输入
3
1 5
2 5
3 5
1
1 2 1 3 6
样例输出
2
解题思路
可持久权值线段树
代码
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#define Maxn 30005
using namespace std;
inline int Getint(){int x=0,f=1;char ch=getchar();while('0'>ch||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
int n,root[Maxn],cnt=0;
struct node{int son[2],L,r,mid,Sum;}Tree[Maxn*56];
void Build2(int v,int L,int r){
Tree[v].L=L;Tree[v].r=r;Tree[v].Sum=0;
Tree[v].son[0]=2*v;
Tree[v].son[1]=2*v+1;
Tree[v].mid=(L+r)/2;
cnt=max(cnt,v);
if(L==r)return;
Build2(2*v,L,(L+r)/2);
Build2(2*v+1,(L+r)/2+1,r);
}
void Build(int &New,int Old,int p,int q){
New=++cnt;
Tree[New]=Tree[Old];
Tree[New].Sum+=q;
if(Tree[New].L==Tree[New].r)return;
if(p<=Tree[New].mid)Build(Tree[New].son[0],Tree[Old].son[0],p,q);
else Build(Tree[New].son[1],Tree[Old].son[1],p,q);
}
void Init(){
n=Getint();
root[0]=1;
Build2(1,1,Maxn);
for(int i=1;i<=n;i++){
int p=Getint(),q=Getint();
Build(root[i],root[i-1],p,q);
}
}
int Calc(int New,int Old,int Min,int Max){
if(Max<Tree[New].L||Tree[New].r<Min)return 0;
if(Min<=Tree[New].L&&Tree[New].r<=Max)return Tree[New].Sum-Tree[Old].Sum;
return Calc(Tree[New].son[0],Tree[Old].son[0],Min,Max)+Calc(Tree[New].son[1],Tree[Old].son[1],Min,Max);
}
bool Check(int &L,int &r,int &Min,int &Need,int x){
int New=root[r];
int Old=root[L-1];
if(Calc(New,Old,Min,x)>=Need)return true;
return false;
}
int main(){
Init();
int q=Getint();
while(q--){
int L=Getint(),r=Getint(),Min=Getint(),Max=Getint(),Need=Getint();
int efL=Min,efr=Max+5;
while(efL<=efr){
int mid=(efL+efr)/2;
if(Check(L,r,Min,Need,mid))efr=mid-1;
else efL=mid+1;
}
if(efr+1>Max)cout<<"-1\n";
else cout<<efr+1<<"\n";
}
return 0;
}