二分+线段树

题目:

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;
}

猜你喜欢

转载自blog.csdn.net/shaohang_/article/details/89076077