dtoj#4263. duliu
題目描述:
小 D 喜歡出毒瘤題毒人。當(dāng)然,他的毒瘤更多體現(xiàn)在若干個(gè)難題組合在同一場(chǎng)比賽時(shí)。
小 D 腦中有 $n$ 個(gè)毒瘤題 idea,第 $i$ 個(gè)的毒值為$d_i$。當(dāng)?shù)?$i$ 個(gè)題和第 $j$ 個(gè)題同時(shí)出現(xiàn)在一場(chǎng)比賽中,會(huì)產(chǎn)生$f(i,j) = d_i + d_j$ 的毒性。
小 D 決定用這些題在 YLOJ 上辦 $m$ 場(chǎng)在線(xiàn)比賽。
? 由于這個(gè) OJ 還在~~咕咕~~開(kāi)發(fā),YLOJ Extremelyhard Round #i 選取的題目編號(hào)集合只能為 $[l_i,r_i]$ 的一個(gè)非空子區(qū)間 $[a_i,b_i]$。
? 因?yàn)檫@個(gè) round 是 extremelyhard 的,所以需要滿(mǎn)足$\sum\limits_{a_i \le j,k \le b_i} f(j,k) \ge x_i$。
? 不過(guò),為了防止題目過(guò)分毒瘤而被噴,小 D 希望最小化$max_{a_i \le j \le b_i} \{d_i\}$,而你需要告訴他這個(gè)最小值。
算法標(biāo)簽:線(xiàn)段樹(shù)
思路:
對(duì)于一個(gè)區(qū)間的答案,可以分為三類(lèi),一類(lèi)是以區(qū)間的左端點(diǎn)作為選擇的區(qū)間作為左端點(diǎn),一類(lèi)是以區(qū)間的右端點(diǎn)作為選擇區(qū)間的右端點(diǎn),一類(lèi)是左右端點(diǎn)在區(qū)間中間,受某個(gè)最大值的限制而不能擴(kuò)大區(qū)間。
因?yàn)闄?quán)值都是正數(shù),所以對(duì)于一個(gè)選擇的區(qū)間如果固定左端點(diǎn),恰好滿(mǎn)足總和限制的最小的區(qū)間最優(yōu),根據(jù)這個(gè)可以先二分計(jì)算出第一類(lèi)和第二類(lèi)的答案。
考慮第三類(lèi),我們對(duì)于每一個(gè)點(diǎn)求出它作為最大值可以延伸的最大區(qū)間。然后當(dāng)這個(gè)區(qū)間被詢(xún)問(wèn)區(qū)間包含的時(shí)候,可以對(duì)答案造成貢獻(xiàn),但是這樣是三維的。我們會(huì)發(fā)現(xiàn)如果你選擇左端點(diǎn)在詢(xún)問(wèn)左端點(diǎn)和這個(gè)詢(xún)問(wèn)第二類(lèi)求的答案區(qū)間的左端點(diǎn)左側(cè),這個(gè)時(shí)候你的答案一旦超過(guò)詢(xún)問(wèn)區(qū)間,這個(gè)答案一定沒(méi)有單獨(dú)取右區(qū)間優(yōu),所以只需要滿(mǎn)足左端點(diǎn)在范圍內(nèi),區(qū)間權(quán)值大于詢(xún)問(wèn)。是一個(gè)二維偏序,可以用線(xiàn)段樹(shù)維護(hù)得到答案。
以下代碼:
#include<bits/stdc++.h> #define il inline #define LL long long #define _(d) while(d(isdigit(ch=getchar()))) using namespace std; const int N=3e5+5,inf=1e9; int n,m,a[N],res[N],tot,Lg[N],st[N][20]; LL sum[N];int mn[N<<2]; struct node{int l,r,ll,id;LL val; }t[N]; struct data{int l,r,mx;LL val; }g[N]; il LL read(){LL x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return f*x; } bool cmp(node t1,node t2){return t1.val>t2.val; } bool cmp1(data t1,data t2){return t1.val>t2.val; } il int getmax(int l,int r){if(l>r)swap(l,r);int k=Lg[r-l+1];return max(st[l][k],st[r-(1<<k)+1][k]); } il int getl(int x,int v){int l=1,r=x,res=x;while(l<=r){int mid=(l+r)>>1;if(getmax(mid,x)<=v)res=mid,r=mid-1;else l=mid+1;}return res; } il int getr(int x,int v){int l=x,r=n,res=x;while(l<=r){int mid=(l+r)>>1;if(getmax(mid,x)<=v)res=mid,l=mid+1;else r=mid-1;}return res; } il LL cal(int l,int r){return (sum[r]-sum[l-1])*(r-l+1)*2; } il int gl(int ql,int qr,LL v){int l=ql,r=qr,res=ql;while(l<=r){int mid=(l+r)>>1;if(cal(ql,mid)>=v)res=mid,r=mid-1;else l=mid+1;}return res; } il int gr(int ql,int qr,LL v){int l=ql,r=qr,res=qr;while(l<=r){int mid=(l+r)>>1;if(cal(mid,qr)>=v)res=mid,l=mid+1;else r=mid-1;}return res; } il void insert(int x,int l,int r,int pos,int v){if(l==r){mn[x]=min(mn[x],v);return;}int mid=(l+r)>>1;if(pos<=mid)insert(x<<1,l,mid,pos,v);else insert(x<<1|1,mid+1,r,pos,v);mn[x]=min(mn[x<<1],mn[x<<1|1]); } il int query(int x,int l,int r,int ql,int qr){if(ql<=l&&r<=qr)return mn[x];int mid=(l+r)>>1;int res=inf;if(ql<=mid)res=query(x<<1,l,mid,ql,qr);if(mid<qr)res=min(res,query(x<<1|1,mid+1,r,ql,qr));return res; } int main() {n=read();m=read();for(int i=1;i<=n;i++)st[i][0]=a[i]=read(),sum[i]=sum[i-1]+a[i];for(int i=2;i<=n;i++)Lg[i]=Lg[i>>1]+1;for(int j=1;j<=Lg[n];j++)for(int i=1;i+(1<<j)-1<=n;i++)st[i][j]=max(st[i][j-1],st[i+(1<<j-1)][j-1]);for(int i=1;i<=n;i++){int l=getl(i,a[i]),r=getr(i,a[i]);LL v=(sum[r]-sum[l-1])*(r-l+1)*2;g[i]=(data){l,r,a[i],v};}for(int i=1;i<=m;i++){int l=read(),r=read();LL x=read();if((sum[r]-sum[l-1])*(r-l+1)*2<x)res[i]=-1;else{int ll=gl(l,r,x),rr=gr(l,r,x);t[++tot]=(node){l,r,rr,i,x};res[i]=min(getmax(l,ll),getmax(rr,r));}}sort(t+1,t+1+tot,cmp);sort(g+1,g+1+n,cmp1);int now=1;for(int i=1;i<=n*4;i++)mn[i]=inf;for(int i=1;i<=tot;i++){while(g[now].val>=t[i].val){insert(1,1,n,g[now].l,g[now].mx),now++;}res[t[i].id]=min(res[t[i].id],query(1,1,n,t[i].l,t[i].ll));}for(int i=1;i<=m;i++)printf("%d\n",res[i]);return 0; } View Code?
轉(zhuǎn)載于:https://www.cnblogs.com/Jessie-/p/10577660.html
總結(jié)
以上是生活随笔為你收集整理的dtoj#4263. duliu的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Paxos共识算法详解
- 下一篇: Delegate