牛客月赛 巅峰对决(线段树)
题目描述
世界第一名侦探牛牛与拥有死亡笔记的牛能互为对方的知音与最强的对手,在某次对决中,牛能给出a[1],a[2],…,a[n]这n个数字,而他会对牛牛进行q次询问,每次询问的类型如下:
1:将a[x]的值改为y。
2:询问[l,r]区间是否可以形成一段连续的数字。若对[l,r]区间的数字从小到大排序之后,有a[l]=a[l+1]-1=a[l+2]-2=…=a[r]−r+l,则认为该区间可以形成一段连续的数字。特别的,当l等于r时,也认为该区间可以形成一段连续的数字。
数据保证,任何时候这n个数字均互不相同。请问牛牛对每个2类型询问的答案是什么?
输入描述:
第一行两个正整数n,q,其中n,q<=1e5。
接下来一行输入n个正整数a[i],a[i]≤1e9。
接下来q行,每行第一个数字op表示询问类型.
若op为1,输入正整数x与y
若op为2,输入正整数l与r
输出描述:
输出牛牛对每个2类型询问的答案,若该区间可以形成一段连续的数字输出YES,否则输出NO。
示例1
输入
5 3
2 5 4 3 1
2 1 5
1 1 8
2 1 5
输出
YES
NO
思路
题目大意是对于某一段查找区间,排序之后能成为公差为1的一段区间则输出YES。否则输出NO,其中有单点更新操作。
考虑使用线段树维护区间内最大数与最小数,由于数字保证不同,当区间长度等于区间内最大数-区间内最小数时,为满足条件。
#include<bits/stdc++.h> using namespace std; int a[100005]; int Max[1000005*2+2]; int Min[1000005*2+2]; void build_tree(int left,int right,int node){ if(left==right){ Max[node]=a[right]; Min[node]=a[right]; return; } int mid=(left+right)/2; int left_node=node*2+1; int right_node=node*2+2; build_tree(left,mid,left_node); build_tree(mid+1,right,right_node); Max[node]=max(Max[left_node],Max[right_node]); Min[node]=min(Min[left_node],Min[right_node]); } void update_tree(int left,int right,int node,int idx,int val){ if(left==right){ Max[node]=val; Min[node]=val; return ; } int mid=(left+right)/2; int left_node=node*2+1; int right_node=node*2+2; if(idx>=left&&idx<=mid){ update_tree(left,mid,left_node,idx,val); } else{ update_tree(mid+1,right,right_node,idx,val); } Max[node]=max(Max[left_node],Max[right_node]); Min[node]=min(Min[left_node],Min[right_node]); } int maxx,minn; void query_tree(int left,int right,int node,int L,int R){ if(R<left||L>right){ return ; } if(L<=left&&R>=right||left==right){///这里要注意是查询区间的范围大于当前区间 maxx=max(Max[node],maxx); minn=min(Min[node],minn); return ; } int mid=(left+right)/2; int left_node=node*2+1; int right_node=node*2+2; query_tree(left,mid,left_node,L,R); query_tree(mid+1,right,right_node,L,R); } int main(){ int n,q,op,x,y,l,r; cin>>n>>q; for(int i=0;i<n;i++){ scanf("%d",&a[i]); } build_tree(0,n-1,0);///建树 /*for(int i=0;i<9;i++){ cout<<"Max="<<" "<<Max[i]<<endl; cout<<"Min="<<" "<<Min[i]<<endl; }*/ for(int i=0;i<q;i++){ cin>>op; if(op==1){ cin>>x>>y; update_tree(0,n-1,0,x-1,y); } if(op==2){ cin>>l>>r; minn=2e9;maxx=0; query_tree(0,n-1,0,l-1,r-1); if(maxx-minn==r-l){cout<<"YES"<<endl;} else cout<<"NO"<<endl; } } return 0; }