hdu 4417(树状数组+离线算法)
生活随笔
收集整理的這篇文章主要介紹了
hdu 4417(树状数组+离线算法)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
解題思路:這道題要求某區間內比h小的個數,其實這里可以類似于樹狀數組求逆序數那樣。關鍵是如何轉換成樹狀數組的模型,這才是本題的難點。
我們首先分析,如果知道h在該區間的哪個位置,那么剩下的就很好做了。我們還可以發現,如果找到了當前的比h小的所有點(大于的點我們先忽略掉),那么我們就可以用樹狀數組求它的[l,r]區間的和。這樣就跟樹狀數組有了一點聯系,但是還不夠,因為我們發現,h的大小會影響我們所要找的區間。什么意思呢?就是我們先找到的是h1,再找h2,但h1>h2,就會出現這樣的問題:h1所對應的區間找到了,但再找h2時,它對應的區間中可能會有比h2大的數,這樣就不符合條件了。所以說這里有一個離線算法,就是先把所有的詢問存下來,再按照h的大小進行從小到大排序,然后根據h的大小,從小到大地一個個插入所有區間內的數,這樣就符合條件了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std;const int maxn = 1e5+5; struct Query {int l,r,h;int id;bool operator < (Query a){return h < a.h;} }q[maxn]; struct Node {int num;int id;bool operator < (Node a){return num < a.num;} }a[maxn]; int n,m; int tree[maxn<<2],ans[maxn];int lowbit(int x) {return x & (-x); }void update(int x,int d) {for(int i = x; i <= n; i += lowbit(i))tree[i] += d; }int getsum(int x) {int sum = 0;for(int i = x; i > 0; i -= lowbit(i))sum += tree[i];return sum; }int main() {int t,cas = 1;cin >> t;while(t--){cin >> n >> m;for(int i = 1; i <= n; i++){cin >> a[i].num;a[i].id = i;}for(int i = 1; i <= m; i++){cin >> q[i].l >> q[i].r >> q[i].h;q[i].l++, q[i].r++;q[i].id = i;}sort(a+1,a+1+n);sort(q+1,q+1+m);memset(tree,0,sizeof(tree));int idx = 1;for(int i = 1; i <= m; i++){while(q[i].h >= a[idx].num && idx <= n){update(a[idx].id,1);idx++;}ans[q[i].id] = getsum(q[i].r) - getsum(q[i].l-1);}printf("Case %d:\n",cas++);for(int i = 1; i <= m; i++)printf("%d\n",ans[i]);}return 0; }
總結
以上是生活随笔為你收集整理的hdu 4417(树状数组+离线算法)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hdu 3303(线段树+抽屉原理)
- 下一篇: hdu 3874(树状数组+离线算法)