일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 정렬
- 삼분탐색
- MST
- 수학
- 이진탐색
- 플로이드와샬
- DisjointSet
- 구현
- 브루트포스
- 투포인터
- 위상정렬
- lca
- 이분탐색
- dfs
- lis
- 좌표압축
- DP
- LazyPropagation
- BFS
- 그리디
- 누적합
- 이분매칭
- 백준
- 다익스트라
- boj
- 크루스칼
- 비트마스크
- 세그먼트트리
- 에라토스테네스의 체
- 펜윅트리
Archives
- Today
- Total
lastknight00
[백준]화려한 마을(12895) 본문
문제 링크 : [백준]화려한 마을(12895)
문제 설명
1번부터 N번까지의 집이 있고, 처음에는모두 1번 색으로 칠해져 있습니다.
Q개의 쿼리를 입력을 받는데 아래와 같은 처리를 합니다.
- C A B C : A번부터 B번까지의 집의 색을 C로 바꿉니다.
- Q A B : A번부터 B번까지의 집까지까지 존재하는 색의 수를 출력합니다.
입력
N(집의 갯수, 1 <= N <= 100,000)
T(색의 갯수, 1 <= M <= 30)
O A B (C)(쿼리 정보)
2 2 4
C 1 1 2
Q 1 2
C 2 2 2
Q 1 2
출력
2
1
카테고리
#세그먼트트리 #LazyPropagation #비트마스크
시간 복잡도 상한
O(QlogN)
해결 방법
- 구간의 값을 업데이트하고, 조회 하는 것이 세그먼트 트리를 이용하면 빠를 것 처럼 생겼습니다.
- 특히 구간을 업데이트 해야하므로 Lazy Propagation을 사용해야 할 것 같습니다.
- 각 집의 색깔은 30까지이므로 1을 왼쪽으로 30번 이동시켜도 int범위에서 해결이 가능합니다.
- 즉, 색깔의 번호 만큼 1을 왼쪽으로 이동시킨 비트(1번이면 2, 2번이면 4...)를 집의 색 상태로 관리합니다.
- 구간의 값은 세그먼트 트리 노드의 자식 노드를 or 연산한 값으로 유지시킵니다.
- 예를 들어, 왼쪽 자식이 1, 2번 색을 사용하였고, 오른쪽 자식이 2, 3번 색을 사용하였으면, 왼쪽 자식의 값은 6(2+4), 오른쪽 자식의 값은 12(4+8)가 되고, 부모 노드는 두 값을 or 연산한 14가 됩니다.
- 조회를 할 때는, 세그먼트 트리 구간값을 조회한 후, 1인 비트의 갯수를 세주면 됩니다.
시간복잡도
O(QlogN)
코드
#include<iostream>
#define N 100001
using namespace std;
int n,q,t[N*4],z[N*4]={0,1},a,b,c;
char o;
void lz(int p,int l,int r){
if(z[p]){
t[p]=(1<<z[p]);
if(l!=r)z[p*2]=z[p*2+1]=z[p];
z[p]=0;
}
}
void u(int p,int l,int r,int x,int y,int c){
lz(p,l,r);
if(y<l||r<x)return;
if(x<=l&&r<=y)z[p]=c,lz(p,l,r);
else u(p*2,l,(l+r)/2,x,y,c),u(p*2+1,(l+r)/2+1,r,x,y,c),t[p]=t[p*2]|t[p*2+1];
}
int qu(int p,int l,int r,int x,int y){
lz(p,l,r);
if(y<l||r<x)return 0;
if(x<=l&&r<=y)return t[p];
return qu(p*2,l,(l+r)/2,x,y)|qu(p*2+1,(l+r)/2+1,r,x,y);
}
int main(){
ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n>>q>>q;
while(q--){
cin>>o>>a>>b;
if(a>b)swap(a,b);
if(o=='C')cin>>c,u(1,1,n,a,b,c);
else {
c=qu(1,1,n,a,b);
a=0;
while(c)a+=c&1,c>>=1;
cout<<a<<"\n";
}
}
}
'PS' 카테고리의 다른 글
[백준]괄호 문자열과 쿼리(17407) (0) | 2020.09.01 |
---|---|
[백준]가로 블록 쌓기(18407) (0) | 2020.08.30 |
[백준]직각다각형(17611) (0) | 2020.08.26 |
[백준]사회망 서비스(SNS)(2533) (0) | 2020.08.22 |
[백준]K번째 최단경로 찾기(1854) (0) | 2020.08.16 |
Comments