1. 程式人生 > >codeforces 765 F 線段樹+set

codeforces 765 F 線段樹+set

兩個 define time fio long begin codeforce spa int

題意:多次詢問區間內 兩數差的絕對值的最小值

題解:離線詢問則可以按照詢問的l排序,倒著詢問,倒著從r更新到l 每次更新i+1到n這個區間,保證這次的更新不會影響到下一次以及以後的更新。因為當兩個區間出現覆蓋時,l更小的那個區間的值一定小於等於另一個,畫個圖就可以明白。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
#include 
<cstring> #include <iomanip> #include <set> #include<ctime> #include<unordered_map> //CLOCKS_PER_SEC #define se second #define fi first #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define Pii pair<int,int> #define Pli pair<ll,int> #define
ull unsigned long long #define pb push_back #define fio ios::sync_with_stdio(false);cin.tie(0) const int N=1e6+10; const ull base=163; const int INF=0x3f3f3f3f; using namespace std; struct node { set<int>s; int mi; }T[N<<2]; struct que { int l,r,id; }q[N<<2];
int a[N]; bool cmp(que a,que b){ if(a.l==b.l&&a.r==b.r)return a.id<b.id; if(a.l==b.l)return a.r<=b.r; return a.l<b.l; } void build(int l,int r,int rt){ T[rt].mi=INF; for(int i=l;i<=r;i++)T[rt].s.insert(a[i]); if(l==r)return ; int m=(l+r)>>1; build(lson); build(rson); } int query(int l,int r,int rt,int L,int R){ if(l>R||L>r)return INF; if(L<=l&&R>=r){ return T[rt].mi; } int m=(l+r)>>1; return min(query(lson,L,R),query(rson,L,R)); } void update(int l,int r,int rt,int L,int R,int v,int &mi){ if(l>R||L>r)return ; if(l==r){ T[rt].mi=min(T[rt].mi,abs(a[l]-v)); mi=min(mi,T[rt].mi); return ; } set<int> &t=T[rt].s; auto p=t.lower_bound(v); if((p==t.end()||*p-v>=mi)&&(p==t.begin()||v-*(--p)>=mi)){ mi=min(mi,query(l,r,rt,L,R)); return ; } int m=(l+r)>>1; update(lson,L,R,v,mi); update(rson,L,R,v,mi); T[rt].mi=min(T[rt<<1].mi,T[rt<<1|1].mi); } int ans[N]; int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } int m;scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%d%d",&q[i].l,&q[i].r); q[i].id=i; } build(1,n,1); sort(q+1,q+1+m,cmp); for(int i=m,l=n;i>=0;i--){ for(;l>=q[i].l;l--){ int tmp=INF; update(1,n,1,l+1,n,a[l],tmp); } ans[q[i].id]=query(1,n,1,q[i].l,q[i].r); } for(int i=1;i<=m;i++){ printf("%d\n",ans[i]); } return 0; }

codeforces 765 F 線段樹+set