日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

Codeforces 1108 E2(线段树+思维)

發(fā)布時(shí)間:2025/4/14 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Codeforces 1108 E2(线段树+思维) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

傳送們

題意:

給你一個長度為nnn的數(shù)列bbb、以及mmm個區(qū)間。
你可以選取111個或多個這樣的區(qū)間aia_iai?,使得令區(qū)間aia_iai?所對應(yīng)的所有值bib_ibi?都減111。你最終要使得max?i=1nbi?min?i=1nbi\max\limits_{i=1}^{n}b_i - \min\limits_{i=1}^{n}b_ii=1maxn?bi??i=1minn?bi?
最大。
問你方案數(shù)以及最大值。

題目分析:

E1E1E1中,我們可以通過這個題中優(yōu)美的性質(zhì),對于每一個區(qū)間aia_iai?,通過枚舉在這個區(qū)間的以及不在這個區(qū)間的兩個點(diǎn),我們就可以用O(b2m)O(b^2m)O(b2m)的時(shí)間復(fù)雜度進(jìn)行求解。

但是在這個題中,nnn的范圍在10510^5105的級別,因此我們需要用一些數(shù)據(jù)結(jié)構(gòu)進(jìn)行優(yōu)化。

我們考慮這幾種情況,對于每一個區(qū)間操作,如果區(qū)間內(nèi)的最小值恰好在要更新的區(qū)間內(nèi),而最大值不在,則此時(shí)答案必定更優(yōu);如果最小值和最大值恰在要更新的區(qū)間內(nèi),則答案不變;如果最大值在而最小值不在,則答案必定更差。

至此,我們可以發(fā)現(xiàn),要使得答案不會變差,當(dāng)且僅當(dāng)最小值恰好在要更新的區(qū)間內(nèi)。

但是我們目前并不知道哪一個點(diǎn)作為最小值點(diǎn)更優(yōu),因此我們可以枚舉最小值點(diǎn)的位置pospospos。根據(jù)我們之前的分析,最小值點(diǎn)能夠防止答案變差,因此那些能夠把我們所枚舉的pospospos包含的區(qū)間必定要更新。而一個區(qū)間要包含一個點(diǎn),則這個區(qū)間至少是那些以該點(diǎn)為起始點(diǎn)的區(qū)間。因此我們只需要在枚舉最小值點(diǎn)位置的過程中,不斷的進(jìn)行區(qū)間?1-1?1即可。

而我們需要注意的是,在我們枚舉的過程中,倘若我們之前更新的某一個區(qū)間不能包含當(dāng)前的位置,我們需要把之前的影響消去,否則會導(dǎo)致將區(qū)間的最大值也減111,導(dǎo)致答案不正確。因此,我們只需要在之前枚舉的過程的最后,把以當(dāng)前位置pospospos為結(jié)尾的所有區(qū)間的影響消去即可。

因?yàn)榇嬖趨^(qū)間更新以及區(qū)間求最大值,因此我們可以用線段樹進(jìn)行維護(hù)。

總的時(shí)間復(fù)雜度為O(nlogn)O(nlogn)O(nlogn)

#include <bits/stdc++.h> #define maxn 100005 using namespace std; typedef pair<int,int>pll; pll q[maxn]; int a[maxn]; vector<int>vec1[maxn]; vector<int>vec2[maxn]; vector<int>res;struct Tree{int add,maxx; }tr[maxn<<2]; void push_up(int rt){tr[rt].maxx=max(tr[rt<<1].maxx,tr[rt<<1|1].maxx); } void push_down(int rt){if(tr[rt].add){tr[rt<<1].maxx+=tr[rt].add;tr[rt<<1|1].maxx+=tr[rt].add;tr[rt<<1].add+=tr[rt].add;tr[rt<<1|1].add+=tr[rt].add;tr[rt].add=0;} } void build(int l,int r,int rt){if(l==r){tr[rt].maxx=a[l];return ;}int mid=(l+r)>>1;build(l,mid,rt<<1);build(mid+1,r,rt<<1|1);push_up(rt); } void update(int L,int R,int l,int r,int rt,int C){if(L<=l&&R>=r){tr[rt].add+=C;tr[rt].maxx+=C;return ;}int mid=(l+r)>>1;push_down(rt);if(L<=mid) update(L,R,l,mid,rt<<1,C);if(R>mid) update(L,R,mid+1,r,rt<<1|1,C);push_up(rt); } int query(int L,int R,int l,int r,int rt){if(L<=l&&R>=r){return tr[rt].maxx;}int mid=(l+r)>>1;push_down(rt);int maxx=-0x3f3f3f3f;if(L<=mid) return max(maxx,query(L,R,l,mid,rt<<1));if(R>mid) return max(maxx,query(L,R,mid+1,r,rt<<1|1));push_up(rt); }int main() {int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++) scanf("%d",&a[i]);build(1,n,1);for(int i=1;i<=m;i++){scanf("%d%d",&q[i].first,&q[i].second);vec1[q[i].first].push_back(q[i].second);//以該點(diǎn)為起點(diǎn)的區(qū)間的右端點(diǎn)vec2[q[i].second].push_back(q[i].first);//以該點(diǎn)為終點(diǎn)的區(qū)間的左短點(diǎn)}int maxx=-0x3f3f3f3f;int pos=0;for(int i=1;i<=n;i++){int tmp=a[i];for(int j=0;j<vec1[i].size();j++){update(i,vec1[i][j],1,n,1,-1);//區(qū)間更新-1}int res=query(1,n,1,n,1)-query(i,i,1,n,1);//區(qū)間求和,等于區(qū)間最大值-當(dāng)前值(最小值)if(maxx<res){maxx=res;pos=i;}for(int j=0;j<vec2[i].size();j++){update(vec2[i][j],i,1,n,1,1);}}cout<<maxx<<endl;int cnt=0;for(int i=1;i<=m;i++){if(q[i].first<=pos&&pos<=q[i].second){res.push_back(i);}cnt++;}cout<<res.size()<<endl;for(auto it:res){cout<<it<<" ";}puts(""); }

轉(zhuǎn)載于:https://www.cnblogs.com/Chen-Jr/p/11007167.html

總結(jié)

以上是生活随笔為你收集整理的Codeforces 1108 E2(线段树+思维)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。