[线段树] Jzoj P3236 矮人排队
题解
- 按照高度建树,维护区间的最大最小值
- 然后我们只用每次查询区间最大最小值,判断一下最大最小值的差与所询问的区间右区间和左区间的差相同就好了
代码
1 #include <cstdio> 2 #include <iostream> 3 using namespace std; 4 int n,m,k1,k2,f[1000000][3],a[300000]; 5 void change(int d,int l,int r,int x,int y) 6 { 7 if (l==r&&l==x) { f[d][1]=f[d][2]=y; return; } 8 int mid=l+r>>1; 9 if (x<=mid) change(d*2,l,mid,x,y); else change(d*2+1,mid+1,r,x,y); 10 f[d][1]=min(f[d*2][1],f[d*2+1][1]),f[d][2]=max(f[d*2][2],f[d*2+1][2]); 11 } 12 void find(int d,int l,int r,int x,int y) 13 { 14 if (x<=l&&r<=y) { k1=min(k1,f[d][1]),k2=max(k2,f[d][2]); return; } 15 int mid=l+r>>1; 16 if (x<=mid) find(d*2,l,mid,x,y); 17 if (y>mid) find(d*2+1,mid+1,r,x,y); 18 } 19 int main() 20 { 21 scanf("%d%d",&n,&m); 22 for (int i=1;i<=n;i++) scanf("%d",&a[i]),change(1,1,n,a[i],i); 23 for (int op,x,y;m;m--) 24 { 25 scanf("%d%d%d",&op,&x,&y); 26 if (op==1) change(1,1,n,a[x],y),change(1,1,n,a[y],x),swap(a[x],a[y]); 27 else 28 { 29 k1=1e9,k2=0,find(1,1,n,x,y); 30 if (k2-k1+1==y-x+1) printf("YES\n"); else printf("NO\n"); 31 } 32 } 33 }