티스토리 뷰
#include <stdio.h>
#include <stdlib.h>
int ETT = 0; //오일로 경로 트릭을 위한 변수
int tree[266000]={}, lazy[266000]={}, arr[100001]={}; //lazy propagation
typedef struct list{ //리스트 자료구조를 위한 구조체
struct list * prev;
struct list * next;
int val;
}list;
void insert(int s, int val, list vec[]) { //리스트에 삽입
list * newNode = (list*) malloc(sizeof(list));
newNode->val = val;
newNode->next = vec[s].next;
newNode->prev = vec+s;
if(vec[s].next != NULL) vec[s].next->prev = newNode;
vec[s].next = newNode;
return;
}
void dfs(int x, int start[], int end[], list vec[]) { //오일러 경로 트릭
start[x] = ++ETT;
for(list* p=vec[x].next; p!=NULL; p=p->next) dfs(p->val, start, end, vec);
end[x] = ETT;
return;
}
void lazyU(int s, int e, int node) { //미룬거 처리
if(lazy[node]) {
tree[node] += (e-s+1) * lazy[node];
if(s!=e) { //말단노드가 아니라면
lazy[node*2] += lazy[node];
lazy[node*2+1] += lazy[node];
}
lazy[node] = 0;
} return;
}
void update(int s, int e, int node, int l, int r, int dif) { //수정(갱신)
lazyU(s,e,node); //미룬거 처리
if(s>r || e<l) return; //범위 밖
if(l<=s && e<=r) { //범위에 속함
tree[node] += (e-s+1) * dif;
if(s!=e) {
lazy[node*2] += dif;
lazy[node*2+1] += dif;
} return;
} //범위에 걸쳤다면 자식노드로
int m=(s+e)/2;
update(s,m,node*2,l,r,dif);
update(m+1,e,node*2+1,l,r,dif);
tree[node] = tree[node*2] + tree[node*2+1]; //수정한 것 반영
return;
}
int find(int s, int e, int node, int l, int r) { //탐색
lazyU(s,e,node); //미룬거 수정
if(s>r || e<l) return 0; //범위 밖
if(l<=s && e<=r) return tree[node]; //범위에 속함
int m=(s+e)/2; //범위에 걸친 경우 자식노드로
return find(s,m,node*2,l,r) + find(m+1,e,node*2+1,l,r);
}
int main(void) {
int n,m,tmp;
scanf("%d %d",&n, &m);
//시작, 종료 번호을 담기위한 배열, 벡터(사실은 리스트) 동적할당
int * start = (int*) malloc(sizeof(int) * (n+1));
int * end = (int*) malloc(sizeof(int) * (n+1));
list * vec = (list*) malloc(sizeof(list) * (n+1));
scanf("%d",&arr[1]); //사장의 월급 입력
for(int i=2; i<=n; i++) { //사원들의 월급, 직속상사 입력
vec[i].prev = vec[i].next = NULL;
scanf("%d %d",&arr[i],&tmp);
insert(tmp, i, vec); //직속상사를 기준으로 vec에 삽입
}
dfs(1, start, end, vec); //ETT
for(int i=1; i<=n; i++) { //초기 월급을 갱신해줌
update(1,n,1,start[i],start[i],arr[i]);
}
while(m--) { //query
char a;
int b,c;
scanf(" %c %d",&a,&b);
if(a=='p') { //update
scanf("%d",&c);
update(1,n,1,start[b],end[b],c); //서브 트리의 노드 포함 갱신
update(1,n,1,start[b],start[b],-c); //서브 트리의 노드 부분만 다시 빼줌 (결국 서브트리의 노드의 값은 변화가 없다)
}
else { //find
printf("%d\n",find(1,n,1,start[b],start[b])); //찾기
}
}
//동적할당 해제
free(start);
free(end);
for(int i=1; i<=n; i++) {
for(list* p=vec[i].next; p!=NULL; p=p->next) free(p);
}
free(vec);
return 0;
}
풀이 : 오일러 경로 트릭, lazy propagation
c언어 14268번 회사 문화 2 (백준)
#include #include int ETT = 0; //ETT에 사용할 변수int tree[266000]={}, lazy[266000]={}; //lazy propagationtypedef struct list{ //리스트 구현을 위한 구조체 struct list * prev; //이전 주소 struct list * next; //이후 주소 int val; //
h202.tistory.com
위의 풀이와 거의 동일합니다.
단지 쿼리 처리과정에서 update부분이 조금 다를 뿐입니다.
주의 : 문제에서 값은 2^31-1 이하라고 했기에 long long int 을 사용하지 않고 int 형으로 처리가 가능합니다.
이 코드는 실행시간이 느린 축에 속합니다.
'c언어 > BAEKJOON' 카테고리의 다른 글
c언어 18437번 회사 문화 5 (백준) (0) | 2024.09.06 |
---|---|
c언어 14287번 회사 문화 3 (백준) (0) | 2024.09.05 |
c언어 14268번 회사 문화 2, 16404번 주식회사 승범이네 (백준) (0) | 2024.09.03 |
c언어 9873번 Cow Baseball (백준) (0) | 2024.09.02 |
c언어 12895번 화려한 마을 (백준) (0) | 2024.08.29 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 오프라인 쿼리
- Segment Tree
- union
- 1835
- 백준
- DP
- Lazy Propagation
- find
- 스택
- C++
- PASCAL
- 최대공약수
- 플로이드
- Krustal
- 기하학
- 세그먼트 트리
- XOR
- 덱
- 최소 스패닝 트리
- 누적 합
- C언어
- 누적합
- 그래프
- DFS
- 1835번
- 그리디
- 브루트포스
- 정렬
- java
- BFS
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함