[LOJ#2732] 「JOISC 2016 Day 2」僱傭計劃

參考博文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 }
相關文章
相關標籤/搜索