e9首先我們有乙個考慮列舉每個mex,計算其貢獻的想法.即有多少個區間的mex
mexme
x是我們當前列舉的這個值.
然後我們手畫一下圖,可以發現,乙個數如果想要成為乙個區間的mex
mexme
x,必須要這個區間已經出現了所有比它小的數.所以可以從小到大列舉mex
mexme
x,然後用r
rr陣列記錄對於乙個左端點,滿足條件的右端點最近的位置,這樣就能幫助我們確定之後的mex
mexme
x在哪些區間.
然後為了列舉時的速度較快,我們用set維護當前"有效"的左端點."有效"的定義是:在列舉到了某個mex
mexme
x後,有些位置的右端點是一樣的,我們維護這些位置中最靠前的乙個.並且只修改這個位置,但是這樣其他位置的mex
mexme
x值沒有變(它們實際也要變).注意到其他位置形成了乙個區間,所以我們想到用線段樹維護這個區間加和.那麼這些數要變化多少呢?我們用lala
la陣列記錄每個位置最後一次作為"有效"位置的mex值是多少,然後加上當前值-la[
i]la[i]
la[i
]就好了.然後我們還要額外記錄這個位置原本的la[
i]la[i]
la[i
],在最後的統計答案的時候減掉.(因為這部分位置原本被認為是另乙個mex並且被更新到線段樹中,我們需要在新一次更新中減去)
時間複雜度o(n
logn
)o(nlogn)
o(nlog
n)
#include
using
namespace std;
typedef
long
long ll;
const
int maxn=
1e6+5;
inline
intread()
while
(isdigit
(c))
return t*f;
}int type,n,a[maxn]
,q;vector<
int> alfa[maxn]
;struct nodeque[maxn]
;struct block};
//記錄操作
bool
cmp2
(block a,block b)
bool
cmp(node a,node b)
set<
int> s;
typedef set<
int>
::iterator it;
int la[maxn]
,r[maxn]
,tot;
it pos[maxn]
;vector b;
void
modify
(int x,
int y,
int val)
for(
int i=
1;i<=tot;i++
)s.erase
(pos[i]);
s.insert
(x);r[x]
=y;la[x]
=val;
}struct tree
inline
void
pushdown
(int rt,
int l,
int r)
void
modify
(int rt,
int l,
int r,
int x,
int y,ll val)
if(tag[rt]
)pushdown
(rt,l,r)
;int mid=
(l+r)
>>1;
if(x<=mid)
modify
(rt<<
1,l,mid,x,y,val);if
(y>mid)
modify
(rt<<1|
1,mid+
1,r,x,y,val)
;pushup
(rt);}
ll query
(int rt,
int l,
int r,
int x,
int y)
if(tag[rt]
)pushdown
(rt,l,r)
;int mid=
(l+r)
>>1;
ll ans=0;
if(x<=mid)ans+
=query
(rt<<
1,l,mid,x,y);if
(y>mid)ans+
=query
(rt<<1|
1,mid+
1,r,x,y)
;return ans;
}}t1,t2;
ll ans[maxn]
;int
main()
q=read()
;for
(int i=
1;i<=q;i++
)que[i]
.l=read()
,que[i]
.r=read()
,que[i]
.id=i;
sort
(que+
1,que+
1+q,cmp)
;//詢問按右端點從小到大排序
for(
int i=
1;i<=n;i++
) r[n+1]
=n+1
; s.
insert(0
);s.
insert
(n+1);
//防止越界
for(
int i=
0;i<=n;i++
) alfa[i]
.push_back
(n+1);
//防止越界
int la=0;
for(
int j:alfa[i])}
sort
(b.begin()
,b.end()
,cmp2)
;int j=0;
for(
int i=
1;i<=q;i++
) ans[que[i]
.id]
=t1.
query(1
,1,n,que[i]
.l,que[i]
.r)*
(que[i]
.r+1
)-t2.
query(1
,1,n,que[i]
.l,que[i]
.r);
}for
(int i=
1;i<=q;i++
)printf
("%lld\n"
,ans[i]);
return0;
}
一道線段樹練習題
注意收到的傷害值寫的有點問題,實際上是a2 j 1 k ai j c j 2 sqrt k a c j 2 a2 j 1k ai,j cj 2 沒有後面的 a 首先由於題目中的限制 選了第i個敵人就再也不能和1到i 1的敵人作戰 我們可以觀察後得出dp ans i min ans u j 1k ai...
一道互動練習題
的做法 考慮逐位確定 對於每個位置,往後列舉有沒有位置可以使得正確位置更多,如果有,那麼有兩種情況,1是這個位置被放到了正確的位置,2是這個位置本來應該放的數被放來了 這裡的重點是我們需要區分1和2 具體的做法是記下讓這個位置答案正確位置數變大的2個位置,將其和i一起移位 這裡是手繪示意圖.即把p1...
一道fft練習題
考場上想到的o n 2 o n 2 o n2 暴力 記f i j f i j f i j 表示前i個位置,長度為j的連擊出現的期望次數 記g i j g i j g i j 表示第到i個位置為止,目前連擊次數為j的概率 轉移時有一些細節 include using namespace std con...