선분 수 입문 상세 설명
선분 수 입문 상세 설명
본문 은 사람들 에 게 적용 된다.
특별히 입문 한 것 은 아 닙 니 다 ~. 본 고 는 선분 나무의 원 리 를 대충 알 고 있 는 것 에 적합 하지만 선분 나무의 조작 에 익숙 하지 않 은 oier or Acmer 입 니 다. 본인 의 수준 이 유한 하고 데이터 구 조 를 깊이 연구 하지 않 았 습 니 다. 큰 신 은 뿌리 지 마 세 요. 궁금 한 점 이 있 으 면 바로 댓 글 에서 말씀 하 세 요. 감사합니다. 잘못 이 있 으 면 지적 해 주세요.
선분 수 대체적인 사고방식
데이터 범위 가 \ (nlog n \) 인 시퀀스 를 보 았 습 니 다. 크게 선분 트 리 로 만 들 었 습 니 다. 선분 트 리 문 제 를 푸 는 방법 1. 문 제 를 수학 식 으로 줄 이 고 유지 할 수 있 는 것 으로 만 듭 니 다. 2. 그 정 보 를 지 키 는 것 을 고려 합 니 다. 3. 어떻게 합 치 는 지 4. 어떻게 내 려 놓 는 지 5. 어떻게 조회 하 는 지
본인 코드 습관
코드 를 이해 하기 위해 서 특별히 설명 합 니 다.
struct Seg {
int l,r,sum;
int lazy;
}tree[];
l 현재 관할 구간 의 왼쪽 끝 점 r 를 유지 하고 현재 관할 구간 의 오른쪽 끝 점 sum 유지 구간 과 lazy 를 유지 하 는 것 은 게 으 름 표시 입 니 다.
#define lson now << 1
#define rson now << 1 | 1
void build(int l,int r,int now) {
tree[now].l = l;tree[now].r = r;
if(l == r) {
XXX;
return;
}
int mid = (l + r) >> 1;
build(l,r,lson);
build(l,r,rson);
updata(now);
}
이상 은 트 리 를 만 드 는 과정 입 니 다. now 는 현재 노드 lson 은 왼쪽 아이 rson 이 고 오른쪽 아이 updatea 는 아버지 에 게 노드 정 보 를 올 리 는 함수 입 니 다. 예 를 들 어 구간 과 이 updatea 함수 는
void updata(int now) {
tree[now].sum = tree[lson].sum + tree[rson].sum;
return;
}
다른 함수 가 있 으 면 다음 글 에서 설명 하 겠 습 니 다.
단점 수정
단점 수정.
void change(int pos,int val,int now) {
if(tree[now].l == tree[now].r) {
tree[now].sum += val;
return ;
}
int mid = (tree[now].l + tree[now].r) >> 1;
if(pos <= mid) change(pos,val,lson);
else change(pos,val,rson);
updata(now);
return;
}
이 함 수 는 이해 하기 가 매우 쉽 습 니 다. 만약 에 조회 한 위치 가 왼쪽 아들 의 관할 범위 에 있다 면 왼쪽 아들 에 게 가서 수정 하 세 요. 오른쪽 아들 은 똑 같 습 니 다. updata 함 수 는 잊 지 마 세 요. 위의 정보 도 수정 해 야 합 니 다. 함 수 를 수정 하려 면 updata 가 필요 합 니 다. 잊 지 마 세 요. 다음은 네 개의 선분 트 리 간 단 함수 의 예 입 니 다.
단일 지점 조회
위의 한 점 수정 과 같 습 니 다. 코드 를 주의 하 세 요. 할 말 이 없습니다. 아마도 선분 트 리 의 가장 간단 한 함수 일 것 입 니 다.
int find(int pos,int now) {
if(tree[now].l == tree[now].r) {
return tree[now].sum;
}
int mid = (tree[now].l + tree[now].r) >> 1;
if(pos <= mid) return find(pos,lson);
else return find(pos,rson);
}
구간 조회
모든 선분 트 리 의 점 은 구간 의 완전한 정 보 를 유지 하기 때 문 입 니 다. 이 점 은 구간 정 보 를 유지 하 는 구간 이 완전히 조회 구간 범위 내 에서 만 답 에 기여 할 수 있 습 니 다. 그렇지 않 으 면 계속 나 눌 수 있 습 니 다. 여 기 는 구간 의 합 을 조회 합 니 다.
int query(int l,int r,int now) {
if(tree[now].l >= l && tree[now].r <= r)
return tree[now].sum;
int mid = (tree[now].l + tree[now].r) >> 1,sum = 0;
if(mid >= l ) sum += query(l,r,lson);
if(mid < r) sum += query(l,r,rson);
return sum;
}
이 부분의 함 수 는 이해 하기 어렵다. 여기 서 구간 을 어떻게 판단 하고 교 제 를 구 하 는 지 에 중점 을 두 고 설명 한다. 여기 서 now 노드 를 조회 하면,계속 나 누 어 조회 해 야 합 니 다. now 관할 구간 은 반드시 조회 구간 과 교 집합 되 어 있 음 을 설명 합 니 다. 여기 서 고려 하 는 것 은 왼쪽 아들 과 조회 해 야 할 구간 이 교 집합 되 어 있 는 지, 오른쪽 아들 과 조회 해 야 할 구간 이 교 집합 되 어 있 는 지 없 는 지 를 고려 하여 아래 의 if 판단 이 있 습 니 다. 합 쳐 진 정 보 를 위로 전달 하 는 것 에 주의 하 세 요.
구간 가감
이 럴 때 는 게 으 름 표 시 를 사용 해 야 합 니 다. 게 으 름 표 시 는 아주 신기 한 것 입 니 다. 게 으 름 표 시 는 시간 을 끌 어 내 리 는 것 을 중시 합 니 다. 구간 이 줄 어 들 때 폭력 업데이트 보다 \ (n ^ 2 \) 알고리즘 이 낫 습 니 다. 게 으 름 표 시 는 구간 을 해결 하 는 것 입 니 다. 게 으 름 표 시 를 사용 하 는 것: 검색, 조작 은 물론 이 고 모두 표 시 를 내 려 놓 아야 합 니 다. 왜 요?하 나 는 비교적 편리 하고 조작 하기 쉬 우 며, 나머지 하 나 는 상 관 없 이, 다른 하 나 는 작업 순서 와 관련 된 것 이다. 예 를 들 어 구간 할당 값 이 1 값 이 되 는 것 이다. 어떻게 하 나 를 표시 합 니까?제목 을 보고 정 합 니 다. 어떤 문 제 는 여러 개의 표 시 를 해 야 합 니 다. 표 시 된 우선 순 위 를 생각해 보 세 요. 이렇게 하면 세 개의 함수 가 더 많아 집 니 다. pushdown 과 modify 와 work 여기 의 lazy 표 시 는 추가 해 야 할 값 입 니 다. 세 개의 함수 에 대한 소개 입 니 다. work 함수
void work(int now , int val) {
tree[now].sum += (tree[now].r - tree[now].l + 1) * val;
tree[now].lazy += val;
}
이 함 수 는 now 선분 트 리 노드 가 관할 하 는 구간 에 하나의 수 를 더 하 는 것 입 니 다. pushdown 함수
void pushdown(int now) {
work(lson,tree[now].lazy);
work(rson,tree[now].lazy);
tree[now].lazy = 0;
return;
}
pushodown 함 수 는 할 말 이 없습니다.
void modify(int l,int r,int now,int val) {
if(tree[now].l >= l && tree[now].r <= r) {
work(now,val);
return ;
}
int mid = (tree[now].l + tree[now].r) >> 1;
if(tree[now].lazy) pushdown(now);
if(mid >= l ) modify(l,r,lson,val);
if(mid < r) modify(l,r,rson,val);
updata(now);
return ;
}
그런데 이게 다 야..
Last
선분 트 리 는 가장 자주 사용 하 는 데이터 기구 중 하나 입 니 다. 매우 많은 세트 는 나중에 일일이 열거 할 것 입 니 다. 다음은 몇 개의 예제 템 플 릿 문 제 를 제시 하여 자신 이 1. 템 플 릿 트 리 모양 배열 1. 템 플 릿 트 리 모양 배열 2. 템 플 릿 선분 트 리 1. 템 플 릿 선분 트 리 25. 간단 한 선분 트 리 템 플 릿 문제 입 니 다.
1. 템 플 릿 문제
#include
#include
const int maxN = 1e6 + 7;
int a[maxN];
inline int max(int x,int y) {
return x > y ? x : y;
}
struct Node{
int l,r,maxx;
int w;
}tree[maxN << 2];
void pushup(int now) {
tree[now].w = tree[now << 1].w + tree[now << 1 | 1].w;
tree[now].maxx = max(tree[now << 1].maxx,tree[now << 1 | 1].maxx);
}
void build(int now,int l,int r) {
tree[now].l = l;tree[now].r = r;
if(l == r) {tree[now].w = a[l];return;}
int mid = (l + r) >> 1;
build(now << 1,l,mid);
build(now << 1 | 1,mid + 1,r);
pushup(now);
}
int query(int l,int r,int now) {
if(tree[now].l >= l && tree[now].r <= r) return tree[now].w;
int Ans = 0;
int mid = (tree[now].r + tree[now].l) >> 1;
if(mid >= l) {Ans += query(l,r,now << 1);}
if(mid < r) {Ans += query(l,r,now << 1 | 1);}
return Ans;
}
inline int read() {
int x = 0,f = 1;char c = getchar();
while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar();}
while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
return x * f;
}
void chang(int x,int now,int pos) {
tree[now].w += x;
if(tree[now].l == tree[now].r) return;
int mid = (tree[now].r + tree[now].l) >> 1;
if(mid >= pos) chang(x,now << 1,pos);
else chang(x,now << 1 | 1,pos);
return;
}
int main() {
int n,m;
n = read();m = read();
for(int i = 1;i <= n;++ i)
a[i] = read();
build(1,1,n);
for(int i = 1,emm,l,r;i <= m;++ i) {
emm = read();
l = read();r = read();
if(emm == 1)chang(r,1,l);
else printf("%d
",query(l,r,1));
}
return 0;
}
2. 템 플 릿 문제
#include
#include
#define X 500007
struct Node{
int l,r,w,lazy;
}tree[X << 2];
void update(int now){
tree[now].w = tree[now << 1].w + tree[now << 1 | 1].w;
return;
}
void down(int now){
int lazy = tree[now].lazy;
if(lazy){
tree[now << 1].lazy += lazy;
tree[now << 1 | 1].lazy += lazy;
tree[now << 1].w += lazy * (tree[now << 1].r - tree[now << 1].l + 1);
tree[now << 1 | 1].w += lazy * (tree[now << 1 | 1].r - tree[now << 1 | 1].l + 1);
tree[now].lazy = 0;
}
}
void build(int l,int r,int now){
tree[now].l = l;tree[now].r = r;
if(l == r){
scanf("%d",&tree[now].w);
return;
}
int mid = (l + r) >> 1;
build(l,mid,now << 1);
build(mid + 1,r,now << 1 | 1);
update(now);
}
void add_inter(int l,int r,int now,int val){
if(tree[now].l >= l && tree[now].r <= r){
tree[now].w += val * (tree[now].r - tree[now].l + 1);
tree[now].lazy += val;
return;
}
int mid = (tree[now].l + tree[now].r ) >> 1;
if(l <= mid){add_inter(l,r,now << 1,val);}
if(r > mid){add_inter(l,r,now << 1 | 1,val);}
update(now);
return;
}
int Point_ask(int pos,int now){
if(tree[now].l == tree[now].r){
return tree[now].w;
}
down(now);
int mid = (tree[now].r + tree[now].l) >> 1;
if(pos <= mid)return Point_ask(pos,now << 1);
else return Point_ask(pos,now << 1 | 1);
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
build(1,n,1);
for(int i = 1,x;i <= m;++ i){
scanf("%d",&x);
if(x == 1){
int l,r,val;
scanf("%d%d%d",&l,&r,&val);
add_inter(l,r,1,val);
}else{
int xx;
scanf("%d",&xx);
printf("%d
",Point_ask(xx,1));
}
}
}
3. 템 플 릿 문제
#include
#include
const int maxN = 1e5 + 7;
#define ll long long
inline int read() {
int x = 0,f = 1;char c = getchar();
while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar();}
while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
return x * f;
}
struct Node{
ll l,r,w,lazy;
}tree[maxN << 2];
ll a[maxN];
void pushdown(ll now) {
ll lazy = tree[now].lazy;
tree[now].lazy = 0;
tree[now << 1].lazy += lazy;
tree[now << 1 | 1].lazy += lazy;
tree[now << 1].w += (tree[now << 1].r - tree[now << 1].l + 1) * lazy;
tree[now << 1 | 1].w += (tree[now << 1 | 1].r - tree[now << 1 | 1].l + 1) * lazy;
return;
}
void updata(ll now) {
tree[now].w = tree[now << 1].w + tree[now << 1 | 1].w;
}
void build(ll l,ll r,ll now) {
tree[now].l = l;tree[now].r = r;
if(l == r) {
tree[now].w = a[l];
return;
}
ll mid = (l + r ) >> 1;
build(l,mid,now << 1);
build(mid + 1,r,now << 1 | 1);
updata(now);
}
void Inter_add(ll l,ll r,ll now,ll val) {
if(tree[now].l >= l && tree[now].r <= r) {
tree[now].w += (tree[now].r - tree[now].l + 1) * val;
tree[now].lazy += val;
return;
}
pushdown(now);
ll mid = (tree[now].l + tree[now].r) >> 1;
if(l <= mid) Inter_add(l,r,now << 1,val);
if(r > mid) Inter_add(l,r,now << 1 | 1,val);
updata(now);
return;
}
ll query(ll l,ll r,ll now) {
if(tree[now].l >= l && tree[now].r <= r) {
return tree[now].w;
}
if(tree[now].lazy)pushdown(now);
ll Ans = 0;
ll mid = (tree[now].l + tree[now].r) >> 1;
if(l <= mid) Ans += query(l,r,now << 1);
if(r > mid ) Ans += query(l,r,now << 1 | 1);
return Ans;
}
int main() {
int n = read(),m = read();
for(int i = 1;i <= n;++ i)
a[i] = read();
build(1,n,1);
for(int i = 1,opt,l,r;i <= m;++ i) {
opt = read();l = read();r = read();
if(opt == 1) {
ll val;
val = read();
Inter_add(l,r,1,val);
}
if(opt == 2) {
printf("%lld
",query(l,r,1));
}
}
return 0;
}
#include
#include
#define ll long long
const ll maxN = 100000 + 7;
using namespace std;
ll a[maxN];
ll mod;
struct Node{
ll l,r,sum;
ll mul,add;
Node() {
add = sum = 0;mul = 1;
}
}tree[maxN << 2];
void qwq(ll now,ll mul,ll add) {
tree[now].mul = tree[now].mul * mul % mod;
tree[now].add = ( tree[now].add * mul % mod + add) % mod;
tree[now].sum = ( (tree[now].sum * mul) % mod +( (tree[now].r - tree[now].l + 1) * add) % mod ) % mod;
}
void updata(ll now) {
tree[now].sum = tree[now << 1].sum + tree[now << 1 | 1].sum;
return;
}
void pushdown(ll now) {
qwq(now << 1,tree[now].mul,tree[now].add);
qwq(now << 1 | 1,tree[now].mul,tree[now].add);
tree[now].mul = 1;
tree[now].add = 0;
}
void build(ll l,ll r,ll now) {
tree[now].l = l;tree[now].r = r;
if(l == r) {
tree[now].sum = a[l];
return;
}
ll mid = (l + r) >> 1;
build(l,mid,now << 1);
build(mid + 1,r,now << 1 | 1);
updata(now);
}
ll query(ll L,ll R,ll now) {
ll l = tree[now].l ,r = tree[now].r;
if(l >= L && r <= R) return tree[now].sum % mod;
if(tree[now].add || tree[now].mul != 1) pushdown(now);
ll sum = 0;
if(L <= (r + l ) >> 1) sum += query(L,R,now << 1);sum %= mod;
if(R > (r + l ) >> 1) sum += query(L,R,now << 1 | 1);
return sum % mod;
}
void Inter_change(ll L,ll R,ll now,ll add,ll mul) {
ll l = tree[now].l,r = tree[now].r;
if(l >= L && r <= R) {
qwq(now,mul,add);
return;
}
ll mid = (r + l) >> 1;
if(tree[now].add || tree[now].mul != 1) pushdown(now);
if(L <= mid) Inter_change(L,R,now << 1,add,mul);
if(R > mid) Inter_change(L,R,now << 1 | 1,add,mul);
updata(now);
}
int main()
{
ll n,m;
scanf("%lld%lld%lld",&n,&m,&mod);
for(ll i = 1;i <= n;++ i)
scanf("%lld",&a[i]);
build(1,n,1);
ll opt,l,r,k;
while(m --) {
scanf("%lld%lld%lld",&opt,&l,&r);
if(opt != 3) {
scanf("%lld",&k);
if(opt == 1) {
Inter_change(l,r,1,0,k);
}
if(opt == 2) {
Inter_change(l,r,1,k,1);
}
}
else printf("%lld
", query(l,r,1));
}
return 0;
}
#include
#include
#define lson now << 1
#define rson now << 1 | 1
#define ll long long
const ll maxN = 10000 + 7;
struct Node {
ll l,r;
ll sum[3];
ll lazy,tag;
}tree[maxN << 2];
void updata(ll now) {
tree[now].sum[1] = tree[lson].sum[1] + tree[rson].sum[1];
tree[now].sum[2] = tree[lson].sum[2] + tree[rson].sum[2];
return ;
}
void build(ll l,ll r,ll now) {
tree[now].l = l;tree[now].r = r;
tree[now].tag = 1;
if(l == r) {
scanf("%d",&tree[now].sum[1]);
tree[now].sum[2] = tree[now].sum[1] * tree[now].sum[1];
return;
}
ll mid = (l + r) >> 1;
build(l,mid,lson);
build(mid + 1,r,rson);
updata(now);
return;
}
void work(ll now,ll lazy,ll tag) {
tree[now].sum[2] = tree[now].sum[2] * tag;
tree[now].sum[1] = tree[now].sum[1] * tag;
tree[now].sum[2] += 2 * tree[now].sum[1] * lazy + (tree[now].r - tree[now].l + 1) * lazy * lazy;
tree[now].sum[1] += (tree[now].r - tree[now]. l + 1) * lazy;
tree[now].lazy = tree[now].lazy * tag + lazy;
tree[now].tag *= tag;
return;
}
void pushdown(ll now) {
work(lson,tree[now].lazy,tree[now].tag);
work(rson,tree[now].lazy,tree[now].tag);
tree[now].lazy = 0;
tree[now].tag = 1;
return ;
}
ll query_1(ll l,ll r,ll now) {
if(tree[now].l >= l && tree[now].r <= r)
return tree[now].sum[1];
ll mid = (tree[now].l + tree[now].r) >> 1,sum = 0;
if(tree[now].lazy || tree[now].tag != 1) pushdown(now);
if(mid >= l) sum += query_1(l,r,lson);
if(mid < r) sum += query_1(l,r,rson);
return sum;
}
ll query_2(ll l,ll r,ll now) {
if(tree[now].l >= l && tree[now].r <= r)
return tree[now].sum[2];
ll mid = (tree[now].l + tree[now].r) >> 1,sum = 0;
if(tree[now].lazy || tree[now].tag != 1) pushdown(now);
if(mid >= l) sum += query_2(l,r,lson);
if(mid < r) sum += query_2(l,r,rson);
return sum;
}
void modify(ll l,ll r,ll now,ll lazy,ll tag) {
if(tree[now].l >= l && tree[now].r <= r) {
work(now,lazy,tag);
return ;
}
ll mid = (tree[now].l + tree[now].r) >> 1;
if(tree[now].lazy || tree[now].tag != 1) pushdown(now);
if(mid >= l) modify(l,r,lson,lazy,tag);
if(mid < r) modify(l,r,rson,lazy,tag);
updata(now);
return ;
}
int main() {
ll n,m;
scanf("%lld%lld",&n,&m);
build(1,n,1);
ll opt,l,r,x;
while(m --) {
scanf("%lld%lld%lld",&opt,&l,&r);
if(opt == 1) printf("%lld
",query_1(l,r,1));
if(opt == 2) printf("%lld
", query_2(l,r,1));
if(opt == 3) {
scanf("%lld",&x);
modify(l,r,1,0,x);
}
if(opt == 4) {
scanf("%lld",&x);
modify(l,r,1,x,1);
}
}
return 0;
}
여기 우리 문제 하나 더 있 는데 풀 어 볼 까요? 어떤 문제 가 잊 어 버 렸 는 지. 문제.
0 l r [l,r]
1 l r [l,r]
2 l r [l,r]
3 l r x [l,r] x
4 l r x [l,r] x
5.l r x [l,r] x
시간 이 있 으 면 그것 을 개인 문제 창고 에 걸 고 시간 이 있 으 면 선분 트 리 의 진급 을 업데이트 할 것 입 니 다.
다음으로 전송:https://www.cnblogs.com/tpgzy/p/9751518.html
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.