無…
n
nn個數,若干組詢問,每一次詢問[l,
r]
[l,r]
[l,r
]中是否經過排序可以形成值域嚴格上公升的序列。
顯然用分塊的思想(記錄上乙個和當前相等的數是否在當前塊外)很容易實現,參見hh的項鍊(有些類似,好像不是一回事,但我找不到之前做的這樣的題了) 。
但時間複雜度卻承受不了。
於是想到了線段樹來維護,那麼時間複雜度降為了θ(n
log2
n)
\theta(nlog^2n)
θ(nlog
2n)。
還是不對勁。
想不到了。
於是翻了題解。暴怒。 原來用has
hhash
hash
的思想,開一棵線段樹維護區間最大值,最小值,平方和(當然用立方和更好,但值域太大,我放棄了)。
那麼,對於一段區間[l,
r]
[l,r]
[l,r
],記最大值為max
maxma
x,最小值為min
minmi
n,平方和為sum
sumsu
m,必然存在r−l
=max
−min
r-l=max-min
r−l=ma
x−mi
n,且∑i=
minm
axi2
=sum
\sum^_i^2=sum
∑i=min
max
i2=s
um。但這不能保證100
%100\%
100%
正確。反例如下:
example:91
1234
5298
9219
correct answer:yuanxing
wrong answer:damushen
因此用三次方能更好的避免衝突。
但是值域為109
10^9
109,很難接受,我還是放棄了。
有一點,在求∑i=
minm
axi2
\sum^_i^2
∑i=min
max
i2的時候會爆lon
glon
glong\ long
longlo
ng,因此無法用字首和+數學推導來求,按照題解的說法,改用迴圈求解,不會超時。
#include
#include
#include
#define ll long long
#define inf (int)(1e9)+1
using
namespace std;
struct node tr[
1000010];
int n,m,len=0;
void
build
(int l,
int r);if
(l}void
change
(int now,
int l,
int r,
int k)
int lc=tr[now]
.lc,rc=tr[now]
.rc,mid=
(tr[now]
.l+tr[now]
.r)>>1;
if(r<=mid)
change
(lc,l,r,k)
;else
if(l>mid)
change
(rc,l,r,k)
;else
change
(lc,l,mid,k)
,change
(rc,mid+
1,r,k)
; tr[now]
.ma=
max(tr[lc]
.ma,tr[rc]
.ma)
; tr[now]
.mi=
min(tr[lc]
.mi,tr[rc]
.mi)
; tr[now]
.sum=tr[lc]
.sum+tr[rc]
.sum;
}node find
(int now,
int l,
int r)
}ll calc
(int x,
int y)
bool
work
(int x,
int y)
intmain()
for(
int i=
1;i<=m;i++)}
}
luogu P3792 由乃與大母神原型和偶像崇拜
題面傳送門 可以算一道線段樹維護hash的模板題了吧。hash要滿足兩個條件 相同的數hash值一定一樣與hash衝突盡量少。這道題hash序列可以用冪次方來hash 然後用線段樹隨便維護一下就好了。實現 include include define max a,b a b a b define m...
Luogu 3792 由乃與大母神原型和偶像崇拜
題面 題目太長怎麼往上放 a 直接說做法吧 要問能不能使這一段區間內的數連續 首先想到的就是最大值減最小值是不是等於區間長度 但是元素可能是重複的 所以我們還要記乙個區間平方和 如果上面的情況已經不符合就直接輸出 否則再判斷一下區間平方和是不是相同 這樣就保證正確了 include include ...
P3792 由乃與大母神原型和偶像崇拜
題意 給你n個數,q次詢問,每次詢問 有 題解 如果這題不帶修改,很多人都會想到,直接用主席樹維護乙個最大值最小值,然後查詢區間不同數的個數,如果不同數的個數等於maxn minn 1 那麼這個區間一定合法。主席樹比較麻煩?那就用線段樹維護乙個最大乙個最小值,乙個這個數第一出現的位置的最小值。如果 ...