先不考慮修改的情況,對所有的權值建一顆線段樹,然後線段樹上儲存下標的資訊,然後每個結點維護子樹下標的最大值。然後對於每次查詢,我直接查詢區間[k,
n+1]
[k,n+1]
[k,n+1
]這段區間值大於r的最小的那個點。
對於修改的情形,實際上每個節點被修改之後相當於刪除,也就是說該節點是可選的,把該節點的下標置為無窮大就可以了。
對於每次查詢,先考慮查詢左子樹,如果左子樹查詢不到答案,再查詢右子樹,可以證明這個複雜度是o(l
og
)o(log)
o(log)
的。對於查詢的區間全部落在左子樹和右子樹的情形,我們歸納到子樹中。剩下的情況只剩下查詢區間橫跨mid這個中點,對於這種情形,答案不存在左子樹中則必定在右子樹中,而右子樹不會出現無解的情形。
#includeusing namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll inf=long_long_max;
const int n=1e5+7;
int a[n];
int mx[n<<2];
void pushup(int rt)
void build(int rt,int l,int r)
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
pushup(rt);
}void modify(int rt,int l,int r,int x,int v)
int mid=(l+r)>>1;
if(x<=mid) modify(rt<<1,l,mid,x,v);
else modify(rt<<1|1,mid+1,r,x,v);
pushup(rt);
}int query(int rt,int l,int r,int l,int r,int v)
if(mx[rt]<=v) return -1;
int mid=(l+r)>>1;
int ans=-1;
if(l<=r&&l<=mid&&mx[rt<<1]>v)
ans=query(rt<<1,l,mid,l,r,v);
if(ans!=-1) return ans;
if(mid+1<=r&&l<=r&&mx[rt<<1|1]>v)
ans=query(rt<<1|1,mid+1,r,l,r,v);
if(ans!=-1) return ans;
return ans;
}int main()
else
} }return 0;
}
HDU6703 array(權值線段樹)
考慮建權值線段樹,那麼線段樹存的值就是它的座標,考慮到答案一定存在且最大值為n 1 n 1n 1,可以多加乙個點n 1 n 1n 1對於操作1 1,x 1,x 1,x 直接單點修改位置s x s x s x 為n 1 n 1n 1 s x 為初始位置x的值 對於操作2 2,r,x 2,r,x 2,r...
權值線緞樹
權值線緞樹就是特殊的線緞樹,他的結構和普通線緞樹一樣,每個結點都是表示一段區間的範圍 因此也需要開四倍空間 但是其每個結點儲存的是該區間的數出現的次數。權值線段樹維護的是桶 形象理解 1 快速計算一段區間的數的出現次數。2 快速找到第k大或第k小值。1 注意題目中資料範圍一般較大,數的值一般高達1e...
2019CCPC網路賽 array(權值線段樹)
題目位址 兩種操作 1.給 a i 10000000 2.查詢不存在 在a 1 r 中 且不低於k的數 在第乙個操作時 由於k的範圍不夠 就相當於把 a i 刪除掉即a i 的下標變為無窮大而對於第二種操作 也就是 等價為在 k之後 的下標的大於r 的可以使用權值線段樹用來維護當前區間最大的 下標如...