鏈接:https://ac.nowcoder.com/acm/contest/9667/B
來源:牛客網
牛牛有n個寶石,第i個寶石的價值是w[i].
有m個操作,操作分為兩種類型
− Change x y 把第x個寶石的價值改成 y
− Ask l r 詢問區間[l,r]內寶石的最大價值,和最大價值的寶石有多少個。
線段樹中查詢區間最大值的時候都是上傳標記的
先查詢左右節點在上傳標記
例:求和中的下傳標記:
要先下傳標記在,查詢左右子節點
void push(int p){ t[2*p].lazy+=t[p].lazy;//下傳標記 t[2*p].s+=1ll*(t[2*p].r-t[2*p].l+1)*t[p].lazy; t[2*p+1].lazy+=t[p].lazy; t[2*p+1].s+=1ll*(t[2*p+1].r-t[2*p+1].l+1)*t[p].lazy; t[p].lazy=0;//還原標記 }
更新時:
push(p);
if(l<=t[2*p].r){ update(2*p,l,r,k); } if(r>=t[2*p+1].l){ update(2*p+1,l,r,k); }
這里的上傳標記(回溯的時候上傳)
上傳標記的時候是根據2*p和2*p+1更新p
void push_up(int p){ t[p].ma=max(t[2*p].ma,t[2*p+1].ma); if(t[2*p].ma==t[2*p+1].ma){ t[p].cnt=t[2*p].cnt+t[2*p+1].cnt; } else if(t[2*p].ma>t[2*p+1].ma){ t[p].cnt=t[2*p].cnt; } else{ t[p].cnt=t[2*p+1].cnt; } }
更新時:
int mid=(t[p].l+t[p].r)/2; if(x<=mid){ update(2*p,x,k); } else{ update(2*p+1,x,k); } push_up(p);
就是在區間求和中建樹中也上傳標記了
t[p].s=t[2*p].s+t[2*p+1].s;
這個題就是:
維護一個區間最值,和一個區間最值的個數,在查詢的時候先找出區間最值,在找出最值出現的次數
上傳標記時:
void push_up(int p){ t[p].ma=max(t[2*p].ma,t[2*p+1].ma); if(t[2*p].ma==t[2*p+1].ma){ t[p].cnt=t[2*p].cnt+t[2*p+1].cnt; } else if(t[2*p].ma>t[2*p+1].ma){ t[p].cnt=t[2*p].cnt; } else{ t[p].cnt=t[2*p+1].cnt; } }
AC代碼:
#include<iostream> #include<algorithm> using namespace std; const int maxn=4e6+100; int a[maxn]; struct node{ int l,r; int ma,cnt; }t[maxn]; int ans1,n,m,x,y; void push_up(int p){ t[p].ma=max(t[2*p].ma,t[2*p+1].ma); if(t[2*p].ma==t[2*p+1].ma){ t[p].cnt=t[2*p].cnt+t[2*p+1].cnt; } else if(t[2*p].ma>t[2*p+1].ma){ t[p].cnt=t[2*p].cnt; } else{ t[p].cnt=t[2*p+1].cnt; } } void build(int p,int l,int r){ t[p].l=l; t[p].r=r; t[p].cnt=0; if(l==r){ t[p].ma=a[l]; t[p].cnt=1; return ; } int mid=(l+r)/2; build(2*p,l,mid); build(2*p+1,mid+1,r); push_up(p); } void update(int p,int x,int k){ if(t[p].l==t[p].r){ t[p].ma=k; t[p].cnt=1; return ; } int mid=(t[p].l+t[p].r)/2; if(x<=mid){ update(2*p,x,k); } else{ update(2*p+1,x,k); } push_up(p); } void query(int p,int l,int r){ int L=t[p].l,R=t[p].r; if(L>=l&&R<=r){ ans1=max(ans1,t[p].ma); return ; } int mid=(L+R)/2; if(l<=mid){ query(2*p,l,r); } if(r>mid){ query(2*p+1,l,r); } push_up(p); } int getcnt(int p,int l,int r){ int L=t[p].l,R=t[p].r; if(L>=l&&R<=r&&t[p].cnt){ if(ans1==t[p].ma){ return t[p].cnt; } else return 0; } int z=0; int mid=(L+R)/2; if(l<=mid){ z+=getcnt(2*p,l,r); } if(r>mid){ z+=getcnt(2*p+1,l,r); } push_up(p); return z; } int main(){ cin>>n>>m; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } build(1,1,n); char str[maxn]; for(int i=1;i<=m;i++){ cin>>str>>x>>y; if(str[0]=='A'){ ans1=0; query(1,x,y); printf("%d %d\n",ans1,getcnt(1,x,y)); } else{ update(1,x,y); } } }