首先转换本质:
就是把一条序列查最高。
故:
使用线段树维护区间最大值
然后倍增。
原型是SCOI2015国旗计划(或者是SCOI2015的那个的原型)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define lc (p<<1)
#define rc (p<<1|1)
using namespace std;
const int N=1e5+100;
inline void read(int &x){
x=0;
int f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-'){
f=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
x*=f;
}
int loc[N]={};
int len[N]={};
int rs[N]={};
int fa[N][30]={};
int C[N][30]={};
int n;
struct Segment_Tree{
struct Node{
int lson,rson,sum,maxsum;
}T[N*4];
void pushup(int p){
T[p].maxsum=max(T[lc].maxsum,T[rc].maxsum);
}
void build(int p,int l,int r){
// cout<<p<<" "<<l<<" "<<r<<'\n';
T[p].lson=l;
T[p].rson=r;
if(l==r){
T[p].maxsum=rs[l];
return;
}
int mid=(l+r)/2;
build(lc,l,mid);
build(rc,mid+1,r);
pushup(p);
}
void update(int p,int pos,int val){
if(T[p].lson==pos&&T[p].rson==pos){
T[p].maxsum=max(T[p].maxsum,val);
return;
}
int mid=(T[p].lson+T[p].rson)/2;
if(pos<=mid){
update(lc,pos,val);
}
else{
update(rc,pos,val);
}
pushup(p);
}
int query(int p,int l,int r){
if(l<=T[p].lson&&T[p].rson<=r){
return T[p].maxsum;
}
int mid=(T[p].lson+T[p].rson)/2;
int ret=0;
if(l<=mid)
ret=max(ret,query(lc,l,r));
if(mid<r)
ret=max(ret,query(rc,l,r));
return ret;
}
}T;
int main(){
read(n);
int maxn=18;
// for(maxn=0;(1<<maxn)<=n;maxn++);
// cout<<(1<<maxn)<<" 123893yuu92"<<'\n';
// maxn--;
for(int i=1;i<=n;i++){
read(loc[i]);
read(len[i]);
}
for(int i=1;i<=n;i++)
rs[i]=loc[i]+len[i];
T.build(1,1,n);
for (int i=n;i>=1;i--){
// cout<<i<<'\n';
int pos=min(n,(int)(upper_bound(loc+1,loc+n+1,rs[i])-loc-1));
int tmp=T.query(1,i,pos);
// cout<<tmp<<'\n';
rs[i]=tmp;
T.update(1,i,rs[i]);
// cout<<"3127890"<<'\n';
fa[i][0]=min(n,(int)(upper_bound(loc+1,loc+n+1,rs[i])-loc));
C[i][0]=max(0,loc[fa[i][0]]-rs[i]);
// cout<<fa[i][0]<<" ";
}
for(int i=1;i<=maxn;i++)
for (int j=1;j<=n;j++){
fa[j][i]=fa[fa[j][i-1]][i-1];
C[j][i]=C[fa[j][i-1]][i-1]+C[j][i-1];
}
// cout<<maxn<<'\n';
/*for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cout<<C[i][j]<<" ";
}
cout<<'\n';
}*/
int Q;
read(Q);
for(int i=1;i<=Q;i++){
int u,v;
read(u);
read(v);
int ans=0;
for(int j=maxn;j>=0;j--)
if (fa[u][j]<=v){
ans+=C[u][j];
u=fa[u][j];
}
printf("%d\n",ans);
}
}