二分+线段树

题目:

C. Store

time limit per test 1.0 s

memory limit per test 256 MB

Ichuan is a store owner and his store has n products, numbered from 11 to nn.

Recently, his business is not very good, and he can occasionally sell a product, so he will confirm the information of the products sold.

MXY,it means that on the XthXth day, the product numbered YY is sold.

DXY,in currently sold products, those whose number is greater than or equal to YY, which one is the lowest number which sold before the XthXth day (including XthXth day) .

Input

the first line contains two positive integers NN,QQ(2≤N,Q≤200000)(2≤N,Q≤200000),which are the number of products and operations.

The following Q lines, each line contains one operator character (MM or DD) and two integers x,yx,y.(1≤x≤109,1≤y≤n1≤x≤109,1≤y≤n)

Output

For each request of type DXYDXY,output the number of required product. If no such product exists, output −1−1.

Examples

input

3 4
M 10 3
M 5 1
D 20 2
D 5 1

output

3
1

input

10 10
M 20 10
D 1 9
M 2 3
D 17 10
M 20 2
D 8 2
M 40 1
D 25 2
M 33 9
D 37 9

output

-1
-1
3
2
9

题意:有编号从1--n的商品,有m种操作,M x y表示更新编号为y的商品卖出的天数为x,D x y表示查询满足编号>=y且卖出的天数<=x的最小编号的商品。

分析:用线段树维护编号为i的商品卖出的最小天数,单点更新,区间查询,最终二分结果即可。

Ac code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+3;
const int INF=1e9+5;
int tree[maxn<<2];///区间查询,单点修改
int n;
void pushup(int rt)
{
    tree[rt]=min(tree[rt<<1],tree[rt<<1|1]);
}
void build(int rt,int l,int r)
{
    if(l==r){
        tree[rt]=INF;
        return;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    pushup(rt);
}
void update(int rt,int p,int l,int r,int val)
{
    if(l==r){
        tree[rt]=val;
        return;
    }
    int mid=(l+r)>>1;
    if(p<=mid) update(rt<<1,p,l,mid,val);
    else update(rt<<1|1,p,mid+1,r,val);
    pushup(rt);
}
int query(int rt,int L,int R,int l,int r)
{
    if(L<=l&&r<=R){
        return tree[rt];
    }
    int mid=(l+r)>>1;
    int ans=INF;
    if(L<=mid) ans=min(ans,query(rt<<1,L,R,l,mid));
    if(mid<R) ans=min(ans,query(rt<<1|1,L,R,mid+1,r));
    return ans;
}
int ask(int l,int r,int val)
{
    int ans=-1;
    while(l<=r){
        int mid=(l+r)>>1;
        if(query(1,l,mid,1,n)<=val){///如果[l,mid]区间内有满足条件的区间可在小一点
            ans=mid;
            r=mid-1;
        }
        else l=mid+1;///否则应在[mid+1,r]找是否有满足条件的
    }
    return ans;
}
int main()
{
    int m;
    scanf("%d%d",&n,&m);
    build(1,1,n);
    char op[10];
    int x,y;
    while(m--){
        scanf("%s%d%d",op,&x,&y);
        if(op[0]=='M') update(1,y,1,n,x);
        else{
            printf("%d\n",ask(y,n,x));
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值