数列
【题目描述】
一个序列有 N 个数,最初每个数均为正无穷大。一共进行 Q 次事件。事件有两种类型:
1. ‘M’ X A 将第 A 个数修改为 X;
2. ‘D’ Y B 查询当前从 B 到 N 的第一个小于或等于 Y 的数的位置,无解返回-1。
已知每个数最多被修改一次(即,数据中所有 1 类事件的 A 互不相同)。
【输入 格式】
输入文件名为 deda.in。
第一行,两个整数 N, Q。
接下来 Q 行,每行描述一次事件。
【输出格式】
输出文件名为 deda.out。
输出若干行,每行一个整数,依次表示每次查询事件的结果。
线段树维护数列,储存的是最小值和位置。查询时如果能到左边优先左,否则右边,返回单个点位置。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+1e2;
const int INF=1e9+1e5;
#define lson (o<<1)
#define rson (o<<1|1)
int minv[MAXN<<2],limitz[MAXN<<2],limitr[MAXN<<2];
struct xds{
inline void pushup(int o){minv[o]=min(minv[lson],minv[rson]);}
void buildt(int o,int l,int r){
limitz[o]=l;limitr[o]=r;
if(l==r){minv[o]=INF;return;}
int mid=(l+r)>>1;
buildt(lson,l,mid);buildt(rson,mid+1,r);
pushup(o);
}
void change(int o,int l,int r,int p,int w){
if(l==p&&r==p){minv[o]=w;return;}
int mid=(l+r)>>1;
if(p<=mid)change(lson,l,mid,p,w);
else change(rson,mid+1,r,p,w);
pushup(o);
}
}xds;
bool flag=0;
void work(int o,int num,int pos){
if(minv[o]>num)return;
if(flag==1)return;
if(limitz[o]==limitr[o]){
printf("%d\n",limitz[o]);
flag=1;
return;
}
if(limitr[lson]>=pos)work(lson,num,pos);
work(rson,num,pos);
}
int n,q;
int main(){
freopen("deda.in","r",stdin);
freopen("deda.out","w",stdout);
char ly;
int hhr,MMMenci;
scanf("%d%d",&n,&q);
xds.buildt(1,1,n);
for(int i=1;i<=q;i++){
cin>>ly;
scanf("%d%d",&hhr,&MMMenci);
if(ly=='D'){
flag=0;
work(1,hhr,MMMenci);
if(!flag)printf("-1\n");
}
else {
xds.change(1,1,n,MMMenci,hhr);
}
}
return 0;
}