나무 커버 트 리 - 선분 나무 커버 밸 런 스 트 리
17336 단어 나무알고리즘 & 데이터 구조 총화 byZZK
선분 트 리 의 역할 은 구간 수정 과 조회 이 고 균형 트 리 의 역할 은 k 대, k 의 순위, 전구, 후계 조회 이다.이 두 가 지 를 결합 하면 구간 수정 과 조회 가 가능 한 k 대, k 의 순위, 전구, 후계 의 데이터 구조: 나무 세트 트 리 - 선분 트 리 세트 균형 트 리 가 된다.
이루어지다
먼저 선분 나 무 를 만 들 고 모든 선분 나 무 는 왼쪽 경계 와 오른쪽 경 계 를 기록 하 는 것 외 에 균형 트 리 (물론 실제 적 으로 뿌리 노드 만 저장 해 야 한다) 를 저장 하여 이 구간 의 모든 수 에 대응 한다.구간 L ~ R 을 수정 할 때마다 L ~ R 을 포함 하 는 모든 선분 트 리 노드 의 밸 런 스 트 리 를 수정 해 야 한다.조작 은 사실 어 려 운 점 이 없습니다. 일반 선분 트 리 와 같이 블록 으로 나 누 어 처리 하면 됩 니 다. 효율 은 O (log 22 (n) 입 니 다.
그러나 검색 구간 k 가 크 면 일반 선분 트 리 처럼 2 점 으로 정 답 mid 를 매 거 한 다음 mid 의 순 위 를 조회 해 야 합 니 다. 순위 < = k 가 크 면 mid 를 늘 리 고 그렇지 않 으 면 mid 를 줄 여야 합 니 다.2 분 간격 이 t 라 고 가정 하면 효율 은 O (log 22 (n) 이 고 8727 ° log 2 (t) 이다.ps: 나무 커버 는 상수 가 많 으 니 조심 하 세 요.
템 플 릿
BZOJ 3196 의 경우 선분 트 리 트 랩 을 사용한다.세부 처리 에 주의 하 세 요.
#include
#include
#include
using namespace std;
const int maxn=50000,maxt=1700000,MAXINT=((1<<30)-1)*2+1;
int n,te,a[maxn+5];
//============================================================
struct Node
{
Node *son[2];
int val,fix,si,w;
int cmp(int k) {if (k==val) return -1;if (kreturn 0; else return 1;}
void Pushup() {si=son[0]->si+w+son[1]->si;}
};
typedef Node* P_node;
Node tem[maxt+5];
P_node null=tem,len=null;
P_node newNode(int k)
{
len++;len->son[0]=len->son[1]=null;
len->si=len->w=1;len->val=k;len->fix=rand();
return len;
}
void Rotate(P_node &p,int d)
{
P_node t=p->son[d^1];p->son[d^1]=t->son[d];t->son[d]=p;
p->Pushup();t->Pushup();p=t;
}
void Insert(P_node &p,int k)
{
if (p==null) {p=newNode(k);return;}
int d=p->cmp(k);
if (d==-1) p->w++; else
{
Insert(p->son[d],k);
if (p->son[d]->fix>p->fix) Rotate(p,d^1);
}
p->Pushup();
}
void Delete(P_node &p,int k)
{
if (p==null) return;
int d=p->cmp(k);
if (d==-1)
{
if (p->w>1) p->w--; else
if (p->son[0]==null) p=p->son[1]; else
if (p->son[1]==null) p=p->son[0]; else
{
int d;if (p->son[0]->fix>p->son[1]->fix) d=0; else d=1;
Rotate(p,d);if (p==null) return;Delete(p->son[d],k);
}
if (p==null) return;
} else Delete(p->son[d],k);
p->Pushup();
}
int getrank(P_node p,int k) // k, k
{
if (p==null) return 1;
int d=p->cmp(k);
if (d==-1) return p->son[0]->si+1; else
if (d==0) return getrank(p->son[0],k); else
return getrank(p->son[1],k)+p->son[0]->si+p->w;
}
int getpre(P_node p,int k)
{
if (p==null) return -MAXINT;
int d=p->cmp(k);
if (d==1) return max(getpre(p->son[1],k),p->val); else
return getpre(p->son[0],k);
}
int getsuf(P_node p,int k)
{
if (p==null) return MAXINT;
int d=p->cmp(k);
if (d==0) return min(getsuf(p->son[0],k),p->val); else
return getsuf(p->son[1],k);
} // Treap
//============================================================
struct SegmentTree
{
int l[4*maxn+5],r[4*maxn+5];P_node ro[4*maxn+5]; //
void Build(int p,int L,int R)
{
l[p]=L;r[p]=R;ro[p]=null;
if (L==R) return;
int mid=L+(R-L>>1);
Build(p<<1,L,mid);Build(p<<1|1,mid+1,R);
}
void Seg_Insert(int p,int L,int k)
{
if (Lreturn;
if (l[p]<=L&&L<=r[p]) Insert(ro[p],k);
// L<=l[p]&&r[p]<=L, L k
if (l[p]==r[p]) return;
Seg_Insert(p<<1,L,k);Seg_Insert(p<<1|1,L,k);
}
void Seg_Delete(int p,int L,int k)
{
if (Lreturn;
if (l[p]<=L&&L<=r[p]) Delete(ro[p],k);
//
if (l[p]==r[p]) return;
Seg_Delete(p<<1,L,k);Seg_Delete(p<<1|1,L,k);
}
int Seg_rank(int p,int L,int R,int k) // -1,
{
if (Rreturn 0;
if (L<=l[p]&&r[p]<=R) return getrank(ro[p],k)-1;
// , L<=l[p]&&r[p]<=R
return Seg_rank(p<<1,L,R,k)+Seg_rank(p<<1|1,L,R,k);
}
int Seg_kth(int l,int r,int k)
{
int L=0,R=1e8;
while (L<=R) //
{
int mid=L+(R-L>>1),rk=Seg_rank(1,l,r,mid)+1;
if (rk<=k) L=mid+1; else R=mid-1;
}
return R;
}
int Seg_pre(int p,int L,int R,int k)
{
if (Rreturn -MAXINT;
if (L<=l[p]&&r[p]<=R) return getpre(ro[p],k);
return max(Seg_pre(p<<1,L,R,k),Seg_pre(p<<1|1,L,R,k));
}
int Seg_suf(int p,int L,int R,int k)
{
if (Rreturn MAXINT;
if (L<=l[p]&&r[p]<=R) return getsuf(ro[p],k);
return min(Seg_suf(p<<1,L,R,k),Seg_suf(p<<1|1,L,R,k));
}
};
SegmentTree tr; //
//============================================================
bool Eoln(char ch) {return ch==10||ch==13||ch==EOF;}
int readi(int &x)
{
int tot=0,f=1;char ch=getchar(),lst=' ';
while ('9''0') {if (ch==EOF) return EOF;lst=ch;ch=getchar();}
if (lst=='-') f=-f;
while ('0'<=ch&&ch<='9') tot=tot*10+ch-48,ch=getchar();
x=tot*f;
return Eoln(ch);
}
void LNR(P_node ro)
{
if (ro==null) return;
LNR(ro->son[0]);for (int i=1;i<=ro->w;i++) printf("%d
",ro->val);LNR(ro->son[1]);
}
int main()
{
freopen("STBST.in","r",stdin);
freopen("STBST.out","w",stdout);
readi(n);readi(te);tr.Build(1,1,n);
for (int i=1;i<=n;i++) readi(a[i]),tr.Seg_Insert(1,i,a[i]);
while (te--)
{
int td,x,y,z;readi(td);readi(x);readi(y);
switch (td)
{
case 1:readi(z);printf("%d
",tr.Seg_rank(1,x,y,z)+1);break;
case 2:readi(z);printf("%d
",tr.Seg_kth(x,y,z));break;
case 3:tr.Seg_Delete(1,x,a[x]);tr.Seg_Insert(1,x,y);a[x]=y;break;
case 4:readi(z);printf("%d
",tr.Seg_pre(1,x,y,z));break;
case 5:readi(z);printf("%d
",tr.Seg_suf(1,x,y,z));break;
}
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
bzoj 3196 tyvj 1730 2 강 평형 수그 중에서 다음 과 같은 조작 을 제공 해 야 합 니 다.(후계 정 의 는 x 보다 크 고 가장 작은 수) 첫 번 째 줄 두 개 수 n, m 는 길이 n 의 질서 있 는 서열 과 m 개의 조작 두 번 째 줄 은 n ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.