洛谷P3616 富金森林公園題解(樹狀陣列)
阿新 • • 發佈:2018-12-16
P3616 富金森林公園
題目描述
博艾的富金森林公園裡有一個長長的富金山脈,山脈是由一塊塊巨石並列構成的,編號從1到N。每一個巨石有一個海拔高度。而這個山脈又在一個盆地中,盆地裡可能會積水,積水也有一個海拔高度,所有嚴格低於這個海拔高度的巨石,就會在水面下隱藏。
由於地殼運動,巨石的海拔高度可能會隨時變化,每次一塊的巨石會變成新的海拔高度。當然,水面的高度也會隨時發生變化。
因為有這樣奇妙的地質奇觀,吸引了很多遊客來遊玩。uim作為一個遊客,可以告訴你此時水位海拔,你得告訴他,能看到有幾個連續露出水面的部分。(與水面持平我們也認為是露出) 輸入輸出格式 輸入格式:
第一行兩個整數N和M,分別表示N塊石頭,M個詢問。
接下來一行,N個整數Ai表示每個巨石的初始海拔。
接下來M行,每行有兩個或者三個數,每一行如果第一個數是1,那麼後面跟一個Bj,表示水面海拔。如果第一個數是2,後面跟兩個整數,Cj和Dj,表示編號Cj的巨石海拔變為Dj。
輸出格式:
對於每個"1"詢問,給出一個整數答案,也就是露出了幾部分的山峰。
輸入輸出樣例
輸入樣例#1:
5 4 8 6 3 5 4 1 5 2 4 1 1 5 1 3
輸出樣例#1:
2 1 2
說明
10%的資料, N,M<=2000
另外30%的資料, 只有"1"的詢問。
100%的資料, 1<=N,M<=200000,1<=Ai,Bj,Dj<=10^9,一定有"1"詢問
這題解法還是挺巧妙的
先考慮暴力
對於水平面高度為x 當h[i-1] < x <= h[i]時 ans++
正解: 觀察暴力, 對於h[i], h[i-1] 我們就給ans[h[i-1]+1 ~ h[i]] 加1 那麼我們可以先對所有高度離散化一下,再搞一顆樹狀陣列或線段樹, 區間修改單點詢問
code:
#include<bits/stdc++.h> using namespace std; const int N = 200010; struct node { int v, id; bool flag; // 0山的高度 1詢問出現的高度 bool operator <(node z) const { return v < z.v; } }h[N<<1]; struct question { int k, c, d; }q[N]; int a[N]; #define lowbit(x) (x&(-x)) int t[N<<1], n, m, s; inline void add(int x, int k) { while (x <= s) { t[x] += k; x += lowbit(x); } return ; } inline int get(int x) { int sum = 0; while (x) { sum += t[x]; x -= lowbit(x); } return sum; } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { h[i].id = i; scanf("%d", &h[i].v); } for (int i = 1; i <= m; i++) { scanf("%d", &q[i].k); if (q[i].k == 1) scanf("%d", &q[i].d); else scanf("%d%d", &q[i].c, &q[i].d); h[i+n].id = i; h[i+n].flag = 1; h[i+n].v = q[i].d; } sort(h+1, h+1+n+m); s = 0; for (int i = 1; i <= m+n; i++) { if (h[i].v != h[i-1].v || i == 1) s++; if (!h[i].flag) a[h[i].id] = s; else q[h[i].id].d = s; } for (int i = 1; i <= n; i++) if (a[i] > a[i-1]) add(a[i-1]+1, 1), add(a[i]+1, -1); for (int i = 1; i <= m; i++) { if (q[i].k == 1) printf("%d\n", get(q[i].d)); else { if (a[q[i].c] > a[q[i].c-1]) add(a[q[i].c-1]+1, -1), add(a[q[i].c]+1, 1); if (a[q[i].c+1] > a[q[i].c]) add(a[q[i].c]+1, -1), add(a[q[i].c+1]+1, 1); a[q[i].c] = q[i].d; if (a[q[i].c] > a[q[i].c-1]) add(a[q[i].c-1]+1, 1), add(a[q[i].c]+1, -1); if (a[q[i].c+1] > a[q[i].c]) add(a[q[i].c]+1, 1), add(a[q[i].c+1]+1, -1); } } return 0; }