Codeforces Round #397 F Souvenirs(线段树)

考虑离线,我们从左往右扫,对于现在的点i,我们先找到离i最近的j使得a[j]>=a[i],然后我们可以知道询问左区间在1~j的询问的答案小于等于a[j]-a[i],我们可以用线段树更新答案,然后还可能存在f=a[i],a[f]-a[i]<=a[j]-a[f],因为a[j]-a[f]已经更新进线段树,所以a[f]<=(a[j]+a[i)/2,我们只要找到里j最近的f即可,然后一直做先去,因为我们发先每次都是除2,所以只要做log(a[i])步就行,然后找的过程也只要离散化a[i]然后开一个查询位置的最大值的线段树即可。

#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=100005;
struct pi{
    int le,ri;
    int ma;
}pp[2][maxn<<2];
void build(int u,int tot,int l,int r){
    pp[u][tot].le=l;
    pp[u][tot].ri=r;
    if(u==1) pp[u][tot].ma=1000000000;
    else pp[u][tot].ma=0;
    if(l==r) return;
    build(u,2*tot,l,(l+r)/2);
    build(u,2*tot+1,(l+r)/2+1,r);
}
void merg(int tot,int x,int p){
    pp[0][tot].ma=max(pp[0][tot].ma,p);
    if(pp[0][tot].le==pp[0][tot].ri) return;
    int mid=(pp[0][tot].le+pp[0][tot].ri)/2;
    if(x<=mid) merg(2*tot,x,p);
    else merg(2*tot+1,x,p);
}
void merg1(int tot,int l,int r,int p){
    if(pp[1][tot].le>=l&&pp[1][tot].ri<=r){
        pp[1][tot].ma=min(pp[1][tot].ma,p);
        return;
    }
    int mid=(pp[1][tot].le+pp[1][tot].ri)/2;
    if(l<=mid) merg1(2*tot,l,r,p);
    if(r>mid) merg1(2*tot+1,l,r,p);
}
int query(int tot,int l,int r){
    if(pp[0][tot].le>=l&&pp[0][tot].ri<=r) return pp[0][tot].ma;
    int s=0;
    int mid=(pp[0][tot].le+pp[0][tot].ri)/2;
    if(l<=mid) s=max(s,query(2*tot,l,r));
    if(r>mid) s=max(s,query(2*tot+1,l,r));
    return s;
}
int query1(int tot,int x){
    if(pp[1][tot].le==pp[1][tot].ri) return pp[1][tot].ma;
    int s=pp[1][tot].ma;
    int mid=(pp[1][tot].le+pp[1][tot].ri)/2;
    if(x<=mid) s=min(s,query1(2*tot,x));
    else s=min(s,query1(2*tot+1,x));
    return s;
}
struct in{
    int l,r;
    int id;
}re[maxn*3];
int a[maxn];
int b[maxn];
int ans[maxn*3];
vectorg[maxn];
void solve(int n,int m){
    for(int i=0;i<2;i++) build(i,1,1,n);
    for(int i=1;i<=n;i++) g[i].clear();
    for(int i=0;i>n;
    for(int i=1;i<=n;i++) {
        scanf("%d",&a[i]);
        b[i]=a[i];
    }
    sort(b+1,b+1+n);
    for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+1+n,a[i])-b;
    int m;
    scanf("%d",&m);
    for(int i=0;i


你可能感兴趣的:(线段树)