'고급' 데이터 구조 - 트 리 배열!
5917 단어 나무.
1. 단점 수정 + 구간 조회
가장 간단 한 트 리 배열 은 다음 과 같다.
void add(int p, int x){ // p x
while(p <= n) sum[p] += x, p += p & -p;
}
int ask(int p){ // p
int res = 0;
while(p) res += sum[p], p -= p & -p;
return res;
}
int range_ask(int l, int r){ //
return ask(r) - ask(l - 1);
}
2. 구간 수정 + 단일 조회
'차이 점' (배열 의 모든 요소 와 이전 요소 의 차 이 를 기록 하 는 것) 을 통 해 이 문 제 를 문제 1 로 바 꿀 수 있다.
조회 하 다.
원래 의 배열 을 a [i] 로 설정 하고 배열 d [i] = a [i] - a [i - 1] (a [0] = 0) 를 설정 하면 a [i] = > ij = 1d [j] 를 설정 하여 d [i] 의 접두사 와 조 회 를 구 할 수 있다.
수정 하 다.
구간 [l, r] 에 x 를 더 했 을 때 a [l] 와 이전 원소 a [l - 1] 의 차 이 는 x, a [r + 1] 과 a [r] 의 차 이 는 x 감소 했다.d [i] 배열 의 정의 에 따라 a [l] 에 x 를 더 하고 a [r + 1] 에 x 를 빼 면 됩 니 다.
void add(int p, int x){ //
while(p <= n) sum[p] += x, p += p & -p;
}
void range_add(int l, int r, int x){ // [l, r] x
add(l, x), add(r + 1, -x);
}
int ask(int p){ //
int res = 0;
while(p) res += sum[p], p -= p & -p;
return res;
}
3. 구간 수정 + 구간 조회
이것 은 가장 자주 사용 하 는 부분 이자 선분 나무 로 가장 번 거 로 운 부분 을 쓰 고 있 습 니 다. 하지만 지금 우 리 는 나무 모양 의 배열 이 생 겼 습 니 다!
어떻게 빌 지?우 리 는 문제 2 의 '차이 점' 방향 을 바탕 으로 문제 2 가 구축 한 트 리 배열 에서 접두사 와:
위치 p 의 접두사 와 = ∑ i = 1pa [i] = ∑ i = 1p ∑ j = 1id [j] 는 등식 의 가장 오른쪽 식 ∑ pi = 1 ∑ ij = 1d [j] 에서 d [1] 는 p 회, d [2] 는 p - 1 로 사용 되 었 다
다음....................................................................................
그러면 우 리 는 두 배열 의 접두사 와: 한 배열 은 sum 1 [i] = d [i] 이 고 다른 배열 은 sum 2 [i] = d [i] 입 니 다.
조회 하 다.
위치 p 의 접두사 와 즉: (p + 1) * sum 1 배열 의 p 접두사 와 - sum 2 배열 의 p 접두사 와.
구간 [l, r] 의 합: 위치 r 의 접두사 와 - 위치 l 의 접두사 와.
수정 하 다.
sum 1 배열 의 수정 과 같은 문제 2 에서 d 배열 의 수정.
sum 2 배열 의 수정 도 비슷 합 니 다. 우 리 는 sum 2 [l] 에 l * x 를 더 하여 sum 2 [r + 1] 에 (r + 1) * x 를 빼 줍 니 다.
void add(ll p, ll x){
for(int i = p; i <= n; i += i & -i)
sum1[i] += x, sum2[i] += x * p;
}
void range_add(ll l, ll r, ll x){
add(l, x), add(r + 1, -x);
}
ll ask(ll p){
ll res = 0;
for(int i = p; i; i -= i & -i)
res += (p + 1) * sum1[i] - sum2[i];
return res;
}
ll range_ask(ll l, ll r){
return ask(r) - ask(l - 1);
}
이 구간 으로 구간 구 화 문 제 를 수정 하 는 것 은 시간 적 으로 나 공간 적 으로 나 레이 지 표 시 된 선분 트 리 보다 우수 하 다.
다른 사내 로 전향 하 다https://blog.csdn.net/zars19/article/details/54620021
단점 수정 구간 조회
#include
#include
#include
#include
using namespace std;
int n,m;
int c[500005];
int lowbit(int x)
{
return (-x)&x;
}
void add(int pos,int x)
{
while(pos<=n)
{
c[pos]+=x;
pos+=lowbit(pos);
}
}
void input()
{
int x;
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
add(i,x);
}
}
int query(int pos)
{
int res=0;
while(pos>0)
{
res+=c[pos];
pos-=lowbit(pos);
}
return res;
}
int main()
{
scanf("%d%d",&n,&m);
input();
int f,x,y;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&f,&x,&y);
if(f==1)
add(x,y);
else if(f==2)
cout<
구간 수정 단점 조회
#include
#include
#include
#include
using namespace std;
int c[500005];
int n,m;
int lowbit(int x)
{
return x&(-x);
}
void add(int pos,int x)
{
while(pos<=n)
{
c[pos]+=x;
pos+=lowbit(pos);
}
}
int query(int pos)
{
int res=0;
while(pos>0)
{
res+=c[pos];
pos-=lowbit(pos);
}
return res;
}
int main()
{
scanf("%d%d",&n,&m);
int x=0,y;
for(int i=1;i<=n;i++)
{
scanf("%d",&y);
add(i,y-x);
x=y;
}
int opt,k;
for(int i=1;i<=m;i++)
{
scanf("%d",&opt);
if(opt==1)
{
scanf("%d%d%d",&x,&y,&k);
add(x,k);
add(y+1,-k);
}
else if(opt==2)
{
scanf("%d",&x);
printf("%d
",query(x));
}
}
return 0;
}
구간 수정 구간 조회 *
여기 서 원수 조 a 를 간략하게 설명 하고 차분 수 조 d 는 an = ∑ i = 1ndi 가 있 기 때문에 ∑ i = 1nai = ∑ i = 1n ∑ j = 1idj = ∑ i = 1n (n − i + 1)×di=(n+1)×∑i=1ndi−∑i=1ndi×i
그래서 우 리 는 두 개의 트 리 배열, c1 저장 di, c2 저장 di 를 유지 합 니 다.×i
#include
#include
#include
using namespace std;
long long c[200005][2];
int n,q;
int lowbit(int x)
{
return x&(-x);
}
void add(int pos,int x,int f)
{
while(pos<=n)
{
c[pos][f]+=x;
pos+=lowbit(pos);
}
}
long long query(int pos,int f)
{
long long res=0;
while(pos>0)
{
res+=c[pos][f];
pos-=lowbit(pos);
}
return res;
}
long long ask(int pos)
{
long long res=(pos+1)*query(pos,0)-query(pos,1);
return res;
}
int main()
{
scanf("%d",&n);
int a=0,b,opt,x;
for(int i=1;i<=n;i++)
{
scanf("%d",&b);
add(i,b-a,0);
add(i,(b-a)*i,1);
a=b;
}
scanf("%d",&q);
for(int i=1;i<=q;i++)
{
scanf("%d",&opt);
if(opt==1)
{
scanf("%d%d%d",&a,&b,&x);
add(a,x,0);
add(b+1,-x,0);
add(a,x*a,1);
add(b+1,-x*(b+1),1);
}
else if(opt==2)
{
scanf("%d%d",&a,&b);
printf("%lld
",ask(b)-ask(a-1));
}
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
예제 1.15 UVALive-3902 트리의 검색컨베이어 도어 제목 대의: n대의 기계는 하나의 트리 네트워크로 연결되어 잎 노드는 클라이언트이고 다른 노드는 서버이다. 처음에는 한 대의 서버만 하나의 서비스를 제공했지만 k의 거리 내의 클라이언트만 덮어쓸 수 있...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.