线段树

原题Manipulate Dwarfs

题意

up为交换两个位置上的人,query为询问以这两个位置为左右边界的区域上的人的编号是不是连在一起,354就是在一起。

解析

因为所以人编号不同,所以只要求出区域内的最大值减去最小值+1是不是等于区域长度即可。用线段树维护最大值和最小值。

代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
#define N 200009
#define rs rt<<1|1
#define ls rt<<1
using namespace std;

struct tree{
    int low,big;
}tr[4*N];
int nu[N];
int n,q;

void build(int l,int r,int rt){
    if(l==r){
        tr[rt].low=tr[rt].big=l;return;
    }
    int mid=l+r>>1;
    build(l,mid,ls);
    build(mid+1,r,rs);
    tr[rt].low=min(tr[ls].low,tr[rs].low);
    tr[rt].big=max(tr[ls].big,tr[rs].big);
}

void update(int l,int r,int rt,int f,int pos){
    if(l==r){
        tr[rt].low=tr[rt].big=f;return;
    }
    int mid=l+r>>1;
    if(pos<=mid)update(l,mid,ls,f,pos);
    else update(mid+1,r,rs,f,pos);
    tr[rt].low=min(tr[ls].low,tr[rs].low);
    tr[rt].big=max(tr[ls].big,tr[rs].big);
}

int Query_max(int l,int r,int rt,int x,int y){
    if(y>=r&&x<=l)return tr[rt].big;
    //为什么是小于等于?查询4~8时,实际上参照段是4~56~8,在查询区间内部 
    int mid=l+r>>1;
    if(mid>=y)return Query_max(l,mid,ls,x,y);
    if(mid<x)return Query_max(mid+1,r,rs,x,y);
    return max(Query_max(l,mid,ls,x,y),Query_max(mid+1,r,rs,x,y));
}

int Query_min(int l,int r,int rt,int x,int y){
    if(y>=r&&x<=l)return tr[rt].low;
    int mid=l+r>>1;
    if(mid>=y)return Query_min(l,mid,ls,x,y);
    if(mid<x)return Query_min(mid+1,r,rs,x,y);
    return min(Query_min(l,mid,ls,x,y),Query_min(mid+1,r,rs,x,y));
}


int main(){
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)nu[i]=i;//nu[1]==2表示第一个位置上的人编号为2 
    build(1,n,1);
    for(int i=1;i<=q;i++){
        int f,a,b;scanf("%d%d%d",&f,&a,&b);
        if(f==1){
            update(1,n,1,nu[a],b);//b位置改成nu[a] 
            update(1,n,1,nu[b],a);
            swap(nu[a],nu[b]);
        }
        else{
            if(Query_max(1,n,1,a,b)-Query_min(1,n,1,a,b)==b-a)
                printf("YES\n");
            else
                printf("NO\n");
        }
    }
} 


//1 10
//3 7

//1 5   6 10
//3 5   6 8
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值