線段樹區間倆個同樣的數

2022-06-08 14:15:14 字數 3783 閱讀 2537

在賣禮物的超市中有n個櫃子,每個櫃子裡都擺放了乙個禮物,每個禮物有自己的乙個編號,第i個櫃子裡的禮物編號為ai​。

茶山牛想給牛牛和牛妹買相同編號的禮物,但禮物有可能在某個時刻被其他人買走,而且櫃子數量太多,因此茶山牛在某個時刻只想知道某乙個櫃子區間是否能買到兩件相同編號的禮物。

具體來說,有q次操作,格式如下:

1  x,第x個櫃子裡的禮物被買走,保證此時這個櫃子裡的禮物還在。

2 l r,茶山牛詢問第l到第r個櫃子未被買走的禮物中是否有兩個禮物編號相同。

對每次茶山牛的詢問輸出一行乙個整數,如果在指定的區間內有兩個禮物編號相同則輸出1,否則輸出0

示例1

複製

5 5

1 2 1 2 1

2 2 4

2 2 5

1 22 2 4

2 2 5

複製

110

1

第一次詢問的時候可以買到兩件編號為2的禮物。第三次詢問的時候由於第二件禮物被買走,所以2到4櫃子裡只有一件編號為1的禮物和一件編號為2的禮物。

第四次詢問的時候可以買到兩件編號為1的禮物。

這個題就是用線段樹維護陣列nextt[i](這個陣列的含義是後面第乙個出現a[i]的下標),這樣維護

到時候只需要查詢一下[l,r]中的最小值看看是不是小於等於r

pre[i]=book[a[i]];//

上一次出現的下標

nextt[book[a[i]]]=i;

book[a[i]]=i;

//這裡book[i]是暫時儲存a[i]的

修改和查詢都是板子

再乙個主要的是這裡如果修改了這個x,x的pre和nextt都要修改

還有線段樹要修改兩次:

1.x的後繼變成inf,

2.pre[x]的後繼變成nextt[pre[x]]

change(1,x,inf);//

維護的是後繼的下標

nextt[pre[x]]=nextt[x];

if(nextt[x]!=inf)

change(

1,pre[x],nextt[pre[x]]);//

維護的後繼的下標,就是他前乙個的後繼要改

#include#include

#include

using

namespace

std;

typedef

long

long

ll;const ll maxn=5e6+9

;ll over=maxn*4

;ll inf=0x3f3f3f3f3f3f3f3f

;struct

nodet[maxn];

ll book[maxn],a[maxn],pre[maxn],nextt[maxn];

intn,q;

void

push_up(ll p)

void

build(ll p,ll l,ll r)

int mid=(l+r)/2

; build(

2*p,l,mid);

build(

2*p+1,mid+1

,r);

t[p].mi=min(t[2*p].mi,t[2*p+1

].mi);

} void

change(ll p,ll x,ll z)

int mid=(t[p].l+t[p].r)/2

;

if(x<=mid)

else

push_up(p);

}ll query(ll p,ll l,ll r)

int mid=(t[p].l+t[p].r)/2

; ll ans=inf;

if(l<=mid)

if(r>mid)

return

ans;

} int

main()

//for(int i=1;i<=n;i++)

//cout/

for(int i=1;i<=n;i++)

//cout/

for(int i=1;i<=n;i++)

//cout

,n);

while(q--)

change(

1,pre[x],nextt[pre[x]]);//

維護的後繼的下標,就是他前乙個的後繼要改

}

else

else}}

}

給你乙個長為n的序列a,有q次詢問。每次詢問給出乙個區間[l,r],詢問al與ar之間是否存在兩個相等的數。

共q+2行。

第一行,兩個整數n,q。

第二行,n個整數a1,a2……an。

接下來q行,每行兩個整數l,r。

對每個詢問輸出一行,yes或no.

樣例輸入 copy

4 2

1 2 3 2

1 32 4

樣例輸出 copy

no

yes

提示對於30%的資料,n,q≤1000,ai≤1000。

對於60%的資料,n,q≤10000。

對於100%的資料,1≤ai≤106,1≤n,q≤105,1≤l≤r≤n,資料有梯度。

#pragma gcc optimize(1)

#pragma gcc optimize(2)

#pragma gcc optimize(3,"ofast","inline")#include

#include

#include

using

namespace

std;

typedef

long

long

ll;const

int maxn=3e6+9

;int

a[maxn];

intne[maxn];

intpre[maxn];

intbook[maxn];

struct

nodet[maxn];

void push(int

p)void build(int p,int l,int

r)

int mid=(l+r)/2

; build(

2*p,l,mid);

build(

2*p+1,mid+1

,r);

push(p);

}int query(int p,int l,int

r)

if(r<=t[2*p].r)

else

if(l>=t[2*p+1

].l)

else

}int

main()

memset(ne,

0x3f,sizeof

(ne));

memset(book,-1,sizeof

(book));

for(int i=n;i>=1;i--)

book[a[i]]=i;//

線段樹

} build(

1,1,n);

for(int i=1;i<=q;i++)

else}}

線段樹的區間修改

1 include 2 include3 define lc p 1 該節點的左孩子 4 define rc p 1 1 右孩子5 using namespace std 67 很類似與樹狀陣列 8int n,m 9struct segment tree 10tree 1000000 線段樹陣列 1...

線段樹的區間加法與區間乘法

題目描述 如題,已知乙個數列,你需要進行下面兩種操作 將某區間每乙個數加上 kk。求出某區間每乙個數的和。輸入格式 第一行包含兩個整數 n,mn,m,分別表示該數列數字的個數和操作的總個數。第二行包含 nn 個用空格分隔的整數,其中第 ii 個數字表示數列第 ii 項的初始值。接下來 mm 行每行包...

線段樹的區間操作 板

區間操作 struct node tr maxn 2 節點型別 void pushup int m void build int m,int l,int r 如果只有乙個節點 int mid l r 1 build m 1,l,mid build m 1 1,mid 1,r 建好左右半邊 pushu...