HDU 4325 离散化+树状数组 或者 不使用树状数组
生活随笔
收集整理的這篇文章主要介紹了
HDU 4325 离散化+树状数组 或者 不使用树状数组
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:給出一些花的開放時間段,然后詢問某個時間點有幾朵花正在開放。
由于ti<1e9,我們需要先將時間離散化,然后將時間點抽象為一個數組中的點,顯然,我們需要進行區間更新和單點查詢,可以考慮線段樹與樹狀數組兩種做法,一般的,樹狀數組是用來維護區間和與單點修改的,那么,如何通過樹狀數組進行區間更新和單點查詢呢,聯想到差分數組,差分數組可以在o(1)的時間內進行區間的更新,但是單點查詢的效率為o(n),顯然不能用于處理此題,這時,考慮樹狀數組維護差分數組,就可以o(logn)地進行區間更新(更新差分數組的 l, r+1即可,使sub[l]++,sub[r+1]--),o(logn)地查詢單點值(求差分數組前綴和)//樹狀數組維護差分數
#include<bits/stdc++.h#define N 100005#define mod 998244353 using namespace std; typedef long long ll; int sub[N<<1],n,l[N],r[N],tim[N],nn; int lowbit(int x){ return x&-x;}; int add(int x,int val) {while(x<=nn){sub[x]+=val;x+=lowbit(x);} } int query(int x) {int ans=0;while (x>0){ans+=sub[x];x-=lowbit(x);}return ans; } int main() {int t;cin>>t;for(int ca=1;ca<=t;ca++){memset(sub,0, sizeof(sub));vector<int>mp;int q,L,R;cin>>n>>q;for(int i=1;i<=n;i++){scanf("%d%d",l+i,r+i);mp.push_back(l[i]);mp.push_back(r[i]);}for(int i=1;i<=q;i++){scanf("%d",tim+i);mp.push_back(tim[i]);}nn=mp.size();sort(mp.begin(),mp.end());unique(mp.begin(),mp.end());for(int i=1;i<=n;i++){L=lower_bound(mp.begin(),mp.end(),l[i])-mp.begin()+1;R=lower_bound(mp.begin(),mp.end(),r[i])-mp.begin()+1;add(L,1);add(R+1,-1);}//for(int i=1;i<=mp.size();i++)cerr<<query(i)<<endl;printf("Case #%d:\n",ca);for(int i=1;i<=q;i++){int pos=lower_bound(mp.begin(),mp.end(),tim[i])-mp.begin()+1;printf("%d\n",query(pos));}}return 0; }?
嚶嚶嚶~~博客寫完,我就后悔了,本題的區間更新和單點查詢操作是分開的,那么我為什么搞這么麻煩還用樹狀數組,直接差分數組求和后不就能o(1)單點查詢了嗎。。但是總體復雜度不變,仍為o(nlogn)
(n為離散化后,映射中點的個數,),常數降低了很多,,雖然運行時間只是由312ms到296ms,但是寫起來簡單了許多,以下是沒有使用樹狀數組的ac代碼
事實證明,只要多思考,問題就會更簡單。算是一點小小的啟發吧
轉載于:https://www.cnblogs.com/xusirui/p/9427708.html
總結
以上是生活随笔為你收集整理的HDU 4325 离散化+树状数组 或者 不使用树状数组的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于async 中return 和 re
- 下一篇: 远程登录服务器配置