Codeforces 622C Not Equal on a Segment(线段树)

题目链接:

http://codeforces.com/contest/622/problem/C

题目大意:

给一个长为n 的序列,m个询问。每次询问一个区间[l,r]和数x。问这个区间里面任意一个不是x的数的位置。

范围:

n,m<=2*10^5。

思路:

可以考虑线段树。利用线段树维护区间上的最大值和最小值。每次询问时看当前区间上的最大和最小值是否与x不同,如果不同,就先往左子树看,如果左子树上面的最大最小值和x相同,就往右子树去看。直到叶子结点,就是答案,否则就是-1。

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#define M 200005
using namespace std;
int max(int a,int b)
{
    return a>b?a:b;
}
int min(int a,int b)
{
    return a<b?a:b;
}
struct tree{
 int l,r,ma,mi;
}tree[M<<2];
int n,m,a[M];
void pushup(int i)
{
    if(tree[i].l==tree[i].r)return;
    tree[i].ma=max(tree[i<<1].ma,tree[i<<1|1].ma);
    tree[i].mi=min(tree[i<<1].mi,tree[i<<1|1].mi);
}
void build(int l,int r,int i)
{
    tree[i].l=l;
    tree[i].r=r;
    int mid=l+r>>1;
    if(l==r){
        tree[i].ma=tree[i].mi=a[tree[i].l];
        return;
    }
    build(l,mid,i<<1);
    build(mid+1,r,i<<1|1);
    pushup(i);
    return;
}
int ans,f;
void query(int l,int r,int i,int z)
{
 if(f)return;
    if(tree[i].l==tree[i].r){
        if(tree[i].ma!=z){f=1;ans=tree[i].l;}
        else ans=-1;
        return;
    }
             int mid=tree[i].l+tree[i].r>>1;
    if(tree[i].ma!=z||tree[i].mi!=z){
         if(r<=mid)query(l,r,i<<1,z);
    else if(l>mid) query(l,r,i<<1|1,z);
  else {
    query(l,mid,i<<1,z);
    query(mid+1,r,i<<1|1,z);
    }


  }
  else {
    ans=-1;
  }
}
int main()
{
    int i,j,k,l,r,m,x;
    while(~(scanf("%d%d",&n,&m)))
    {
        for(i=1;i<=n;i++)
            scanf("%d",&a[i]);
            build(1,n,1);
            while(m--)
            {
                f=0;
                scanf("%d%d%d",&l,&r,&x);
                query(l,r,1,x);
                       printf("%d\n",ans);
            }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值