题目描述:
题目分析:
把时间看做线段上的一个个格子组成,每个格子的水量变化由格子开始的水速决定。
水速是很容易用线段树维护的,所以区间[l,r]的水量变化就可以维护。
询问就只需要在线段树上二分就行了。
具体的,线段树节点的成员是这样的(注意时间范围很大,而下面的代码并没有离散化所以是动态开点的):
struct node{
int ch[2],v;//左右儿子,区间起始点的水速(只有l==r||cov==1有意义)
bool cov;//是否被覆盖
LL sum,lsum;//总流量,前缀最小流量
}t[maxn*40];
改变一个时刻的水速以及删除操作用map可以很方便的得出修改区间(感叹STL的强大,详见代码)
Code:
#include<bits/stdc++.h>
#define maxn 100005
#define x first
#define y second
#define LL long long
using namespace std;
struct node{
int ch[2],v;
bool cov;
LL sum,lsum;//总流量,前缀最小流量
}t[maxn*40];
#define lc t[i].ch[0]
#define rc t[i].ch[1]
int Q,root,sz;
void upd(int i){
if(!lc) lc=++sz;
if(!rc) rc=++sz;
t[i].sum=t[lc].sum+t[rc].sum;
t[i].lsum=min(t[lc].lsum,t[lc].sum+t[rc].lsum);
}
void cover(int &i,int l,int r,int v){
if(!i) i=++sz;
t[i].cov=1,t[i].v=v;
t[i].sum=1ll*(r-l+1)*v;
t[i].lsum=(v>=0?0:t[i].sum);
}
void pushdown(int i,int l,int mid,int r){
if(t[i].cov){
cover(lc,l,mid,t[i].v);
cover(rc,mid+1,r,t[i].v);
t[i].cov=0;
}
}
void insert(int &i,int l,int r,int x,int y,int v){
if(!i) i=++sz;
if(x<=l&&r<=y) {cover(i,l,r,v);return;}
int mid=(l+r)>>1;
pushdown(i,l,mid,r);
if(x<=mid) insert(lc,l,mid,x,y,v);
if(y>mid) insert(rc,mid+1,r,x,y,v);
upd(i);
}
typedef pair<double,LL> pdl;
pdl query(int &i,int l,int r,int x,int y,LL s){
if(!i) i=++sz;
if(x<=l&&r<=y){
if(s+t[i].lsum>0) return make_pair(-1,t[i].sum);
if(l==r||t[i].cov) return make_pair(l-1.0*s/t[i].v,t[i].sum);
}
int mid=(l+r)>>1;
pushdown(i,l,mid,r);
if(y<=mid) return query(lc,l,mid,x,y,s);
if(x>mid) return query(rc,mid+1,r,x,y,s);
pdl lret = query(lc,l,mid,x,y,s);
if(lret.x>0) return lret;
pdl rret = query(rc,mid+1,r,x,y,s+lret.y);
return make_pair(rret.x,lret.y+rret.y);
}
const int N = 1e9;
map<int,int>T;
int main()
{
scanf("%d",&Q);
T[0]=T[N+1]=0;
int op,l,r,v;
while(Q--){
scanf("%d%d",&op,&l);
if(op==1){
scanf("%d",&v); T[l]=v;
auto it = T.find(l); it++;
insert(root,1,N,l,it->x-1,v);
}
else if(op==2){
auto it = T.find(l), pre = it, nxt = it;
pre--, nxt++; T.erase(it);
insert(root,1,N,l,nxt->x-1,pre->y);
}
else{
scanf("%d%d",&r,&v);
if(!v) printf("%d\n",l);
else if((l=T.lower_bound(l)->x)>=r) puts("-1");
else{
auto ans = query(root,1,N,l,r-1,v);
if(ans.x<0) puts("-1");
else printf("%.10f\n",ans.x);
}
}
}
}