1. 程式人生 > 實用技巧 >線段樹維護區間最大值和最小值

線段樹維護區間最大值和最小值

連結:https://ac.nowcoder.com/acm/contest/6874/D
來源:牛客網

世界第一名偵探牛牛與擁有死亡筆記的牛能互為對方的知音與最強的對手,在某次對決中,牛能給出a[1],a[2],…,a[n]n個數字,而他會對牛牛進行q次詢問,每次詢問的型別如下:

1:將a[x]的值改為y

2:詢問[l,r]區間是否可以形成一段連續的數字。若對[l,r]區間的數字從小到大排序之後,有a[l]=a[l+1]−1=a[l+2]−2=…=a[r]−r+l,則認為該區間可以形成一段連續的數字。特別的,當l等於r時,也認為該區間可以形成一段連續的數字。

資料保證,任何時候這n個數字均互不相同

。請問牛牛對每個2型別詢問的答案是什麼?

因為說這n個數互不相同,所以只需要判斷區間裡的max-min是否等於期間長度就行

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
//c(n,k)*c(m,k)*k! 
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while
(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } const int maxn=1e6+100; int a[maxn],n,m; int maxx=0; int minx=0x3f3f3f3f; struct node{ int l,r,ma,mi; }t[maxn]; void push_up(int p){ t[p].ma=max(t[2*p].ma,t[2*p+1].ma); t[p].mi=min(t[2*p].mi,t[2*p+1].mi); } void build(int
p,int l,int r){ t[p].l=l; t[p].r=r; if(l==r){ t[p].mi=a[l]; t[p].ma=a[l]; return ; } int mid=(l+r)/2; build(2*p,l,mid); build(2*p+1,mid+1,r); push_up(p); } void change(int p,int x,int k){ int L=t[p].l,R=t[p].r; if(L==R){ t[p].ma=k; t[p].mi=k; return ; } int mid=(L+R)/2; if(x<=mid){ change(2*p,x,k); } else{ change(2*p+1,x,k); } push_up(p); } void qmax(int p,int l,int r){ int L=t[p].l,R=t[p].r; if(L>=l&&R<=r){ maxx=max(maxx,t[p].ma); minx=min(minx,t[p].mi); return ; } int mid=(L+R)/2; if(l<=mid){ qmax(2*p,l,r); } if(r>mid){ qmax(2*p+1,l,r); } push_up(p); } int main(){ cin>>n>>m; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } build(1,1,n); int op,x,y; for(int i=1;i<=m;i++){ scanf("%d%d%d",&op,&x,&y); if(op==1){ change(1,x,y); } else{ minx=0x3f3f3f3f; maxx=0; qmax(1,x,y); //cout<<maxx<<" "<<minx<<endl; if((maxx-minx+1)==(y-x+1)){ printf("YES\n"); } else{ printf("NO\n"); } } } }