題目鏈結
題目大意:給定乙個只含$0$和$1$的序列。有三種操作:1.把$[l,r]$內所有數改為$0$;2.把$[l,r]$內所有$1$拿走來填$[l',r']$內所有$0$。多了丟掉,少了優先從左開始填;3.查詢$[l,r]$內最長的$0$串。
一眼能看出來考最大子段和。但是**好難調啊qaq
對於一段序列,我們要維護$4$個東西:$ls,rs,ms,s$,分別為從左端點開始最長的$0$串,從右端點開始最長的$0$串,序列內最長的$0$串,序列和。
維護最大子段和,無非就兩種情況:跨過$mid$和沒有跨過$mid$。注意在維護$ms$的時候有三種情況:左兒子的$ms$,右兒子的$ms$,左兒子$rs$加右兒子$ls$。也可以翻我之前的部落格。
對於區間修改我們維護乙個$lazy$,在$pushdown$的時候維護一下序列就好。
最後說一下$2$操作。我們注意到在一段序列內的和是非嚴格單調遞增的。所以要確定我們填的這個區間,我們只需二分一下這個右端點即可。
然後就是噁心人的調**時間了。壓過行後也有130行……
時間複雜度$o(n\log^2 n)$
**:
#includeusingnamespace
std;
const
int maxn=200005
;int
n,m;
struct
node
tree[maxn*4
];inline
intread()
while(isdigit(ch))
return x*f;
}inline
void pushup(int
index)
inline
void build(int index,int l,int
r)
int mid=(l+r)>>1
; build(index*2
,l,mid);
build(index*2+1,mid+1
,r);
pushup(index);
}inline
void pushdown(int index,int l,int r)//
ms,ls,rs,s,lazy
if (tree[index].lazy==1
)
tree[index].lazy=-1;}
inline
void update(int index,int l,int r,int ql,int qr,int
k) pushdown(index,l,r);
int mid=(l+r)>>1
;
if (ql<=mid) update(index*2
,l,mid,ql,qr,k);
if (qr>mid) update(index*2+1,mid+1
,r,ql,qr,k);
pushup(index);
}inline
int querysum(int index,int l,int r,int ql,int
qr)inline
int queryrest(int index,int l,int r,int ql,int
qr)inline
int querymax(int index,int l,int r,int ql,int
qr)
return
res;
}inline
void work(int l0,int
r0) update(
1,1,n,l1,ans,1);}
intmain()
return0;
}
SHOI2015 腦洞治療儀
我太sb啦 合併的時候又漏了,又漏了,又漏了 我個sb 這是個板子題,並不知道為什麼shoi2015會考這麼板子的題,但是我又sb了,又sb了,又sb了,又沒有1a 顯然我是涼了 這道題有三個操作 區間清零 將乙個區間清零,之後補到另乙個區間去,但是有可能補不滿 詢問乙個區間內最大全零子串 顯然這都...
SHOI2015 腦洞治療儀
嘟嘟嘟 這題其實就是乙個線段樹維護最大連續和的水題。別的操作不說,操作1只要二分找區間前 k 個0即可。需要注意的是,因為操作1兩區間可能有交,因此要先清空再二分查詢 複雜度 o n log 2 n include include include include include include in...
SHOI2015 腦洞治療儀
洛谷題目鏈結 珂朵莉樹吼啊!對於操作 0 其實就是區間賦值為 0 的操作,直接套模板就行了 對於操作 1 應該是這個題目最難的操作了 雖然還是很簡單 我們先查詢 l 0,r 0 這個區間的 1 的數量,最後掃一遍 l 1,r 1 這個區間,如果 1 的數量夠的話直接更改區間值,如果不夠的話就把其中夠...