https://unorderedmap.tistory.com/11
수열과 쿼리 15와 거의 같은 문제이나, 조건 하나가 추가되었다.
문제 요약
길이 10만 이하의 수열에서 2가지 쿼리를 수행한다.
1 i v : i번째 값을 v로 바꾼다.
2 i j : 수열의 i번째 원소부터 j번 원소까지 중에서 가장 작은 값을 가지는 인덱스를 출력한다. 단, 최솟값이 여러 개일 경우 가장 작은 인덱스를 출력한다.
https://www.acmicpc.net/problem/14428
사용 알고리즘
세그먼트 트리
풀이
pair을 담는 세그먼트 트리를 잡자. first에는 해당 구간의 최솟값, second에는 해당 구간에서 최솟값을 가지는 가장 작은 인덱스를 저장한다. pair은 크기 비교 시 first가 작은 것이 먼저, first가 같은 경우 second가 작은 것이 먼저이므로 가장 기본적인 min seg를 통해 구현할 수 있다.
수열과 쿼리 15에서는 쿼리가 전체 구간에 대해서만 들어왔지만, 이번에는 부분 구간에 대해서도 들어오기 때문에 출력 쿼리에 대한 답을 구해주는 함수가 필요하다. 다만 세그먼트 트리를 구현해 본 사람이라면 이 역시 어렵지 않게 처리해줄 수 있고, 그래서 두 문제의 티어가 같은 것 같다.
코드
더보기
#include<bits/stdc++.h>
#define SIZE 100010
using namespace std;
int N,Q,A[SIZE];
pair<int,int>seg[SIZE*4];
void init(int l,int r,int node)
{
if(l>r)return;
if(l==r){
seg[node]={A[l],l};
return;
}
int mid=l+r>>1;
init(l,mid,node*2);
init(mid+1,r,node*2+1);
seg[node]=min(seg[node*2],seg[node*2+1]);
}
void update(int l,int r,int node,int s,int w)
{
if(l>r)return;
if(l==s&&r==s){
seg[node]={w,s};
return;
}
if(l>s||r<s)return;
int mid=l+r>>1;
update(l,mid,node*2,s,w);
update(mid+1,r,node*2+1,s,w);
seg[node]=min(seg[node*2],seg[node*2+1]);
}
pair<int,int>query(int l,int r,int node,int s,int e)
{
if(l>r)return {1e9,1e9};
if(s<=l&&r<=e)return seg[node];
if(l>e||r<s)return {1e9,1e9};
int mid=l+r>>1;
return min(query(l,mid,node*2,s,e),query(mid+1,r,node*2+1,s,e));
}
int main()
{
cin>>N;
for(int i=1;i<=N;i++)scanf("%d",&A[i]);
init(1,N,1);
for(cin>>Q;Q--;){
int tc,s,e;scanf("%d %d %d",&tc,&s,&e);
if(tc-1)printf("%d\n",query(1,N,1,s,e).second);
else update(1,N,1,s,e);
}
}
https://unorderedmap.tistory.com/13
'문제 풀이' 카테고리의 다른 글
수열과 쿼리 37 [BOJ 18436] (0) | 2022.02.02 |
---|---|
수열과 쿼리 24 [BOJ 17408] (0) | 2022.02.01 |
수열과 쿼리 9 [BOJ 13554] (2) | 2022.01.28 |
수열과 쿼리 17 [BOJ 14438] (0) | 2022.01.26 |
수열과 쿼리 15 [BOJ 14427] (0) | 2022.01.24 |