參考博文c++
(不過我的感受我講的稍微更清楚一點)git
題目就是讓咱們求圖中知足數值大於等於B的連通塊數量數組
而後咱們能夠嘗試轉換爲求連通塊兩端所產生的「谷」的數量,顯然一個連通塊對谷能夠貢獻2的答案,最終答案就是谷的數量除以2數據結構
(下圖爲查詢$B_i$大小爲4時的狀況,每個箭頭表明一個谷)spa
發現每兩個數中間的空格都是有可能產生谷的,因此咱們只須要維護有多少個空格知足產生谷的條件便可.net
記一個空格左邊的數字爲X,右邊的數字爲Y,當前詢問爲B,觀察發現,當且僅當知足下列條件時,這個空格能夠成爲谷code
$$min(X,Y)+1 \leq B \leq max(X,Y)$$blog
咱們須要一種能夠在$logn$的複雜度內維護知足上述條件點的數量,支持單點修改區間查詢的數據結構,發現樹狀數組能夠很好的知足這個要求、get
咱們把這個詢問條件差分一下扔到樹狀數組裏維護便可it
一些注意點:
開始更新的時候要把0和n+1這兩個節點也算進去,以避免漏記錄兩端的「谷」
觀察到$a_i$,$b_i$很大,咱們須要進行必要的離散化
代碼:
1 //hgs AK IOI,IMO,ICHO,IPHO 2 #include<bits/stdc++.h> 3 #define writeln(x) write(x),puts("") 4 #define writep(x) write(x),putchar(' ') 5 using namespace std; 6 inline int read(){ 7 int ans=0,f=1;char chr=getchar(); 8 while(!isdigit(chr)){if(chr=='-') f=-1;chr=getchar();} 9 while(isdigit(chr)){ans=(ans<<3)+(ans<<1)+chr-48;chr=getchar();} 10 return ans*f; 11 }void write(int x){ 12 if(x<0) putchar('-'),x=-x; 13 if(x>9) write(x/10); 14 putchar(x%10+'0'); 15 }const int M= 6e5+5; 16 int s[M],n,m,x,y,z,b[M],len,v[M]; 17 struct P{int opt,x,y;}q[M]; 18 #define low(x) (x&-x) 19 inline int GetNum(int x){return lower_bound(b+1,b+len+1,x)-b;} 20 inline void Update(int x,int y){for(++x;x<=n*3;x+=low(x))s[x]+=y;} 21 inline int Query(int x){int ans=0;for(++x;x;x-=low(x))ans+=s[x];return ans;} 22 inline void Init(){int tot=0;//離散化 + 樹狀數組初始化 23 for(int i=1;i<=n;i++)b[++tot]=v[i]; 24 for(int i=1;i<=m;i++)if(q[i].opt==1)b[++tot]=q[i].x;else b[++tot]=q[i].y; 25 sort(b+1,b+tot+1),len=unique(b+1,b+tot+1)-b-1; 26 for(int i=1;i<=n;i++)v[i]=GetNum(v[i]); 27 for(int i=1;i<=m;i++)if(q[i].opt==1)q[i].x=GetNum(q[i].x);else q[i].y=GetNum(q[i].y); 28 for(int i=1;i<=n+1;i++){ 29 int l=v[i-1],r=v[i]; 30 if(l>r)swap(l,r); 31 Update(++l,1),Update(++r,-1); 32 } 33 } 34 inline void Add(int x,int y){ 35 int l=v[x-1],r=v[x]; 36 if(l>r)swap(l,r); 37 Update(++l,y),Update(r+1,-y); 38 l=v[x],r=v[x+1]; 39 if(l>r)swap(l,r); 40 Update(++l,y),Update(r+1,-y); 41 } 42 inline void Solve(){ 43 for(int i=1;i<=m;i++) 44 if(q[i].opt==1)printf("%d\n",Query(q[i].x)/2); 45 else Add(q[i].x,-1),v[q[i].x]=q[i].y,Add(q[i].x,1); 46 } 47 int main(){ 48 n=read(),m=read(); 49 for(int i=1;i<=n;i++)v[i]=read(); 50 for(int x,y,z,i=1;i<=m;i++){ 51 if((x=read())==1)q[i].opt=1,q[i].x=read(); 52 else q[i].opt=2,q[i].x=read(),q[i].y=read(); 53 }Init();Solve(); 54 return 0; 55 }