duliu——思维+线段树
题目
【题目描述】
小 `D` 喜欢出毒瘤题毒人。当然,他的毒瘤更多体现在若干个难题组合在同一场比赛时。
小 `D` 脑中有 $n$ 个毒瘤题 idea,第 $i$ 个的毒值为$d_i$。当第 $i$ 个题和第 $j$ 个题同时出现在一场比赛中,会产生$f(i,j) = d_i + d_j$ 的毒性。
小 `D` 决定用这些题在 YLOJ 上办 $m$ 场在线比赛。
• 由于这个 OJ 还在~~咕咕~~开发,`YLOJ Extremelyhard Round #i` 选取的题目编号集合只能为 $[l_i,r_i]$ 的一个非空子区间 $[a_i,b_i]$。
• 因为这个 round 是 extremelyhard 的,所以需要满足$\sum\limits_{a_i \le j,k \le b_i} f(j,k) \ge x_i$。
• 不过,为了防止题目过分毒瘤而被喷,小 `D` 希望最小化$max_{a_i \le j \le b_i} \{d_i\}$,而你需要告诉他这个最小值。
【输入格式】
从文件 `duliu.in` 中读入数据。
第一行,正整数$n$,自然数$m$。
第二行,$n$ 个正整数,第 $i$ 个元素代表$d_i$。
接下来 $m$ 行,每行三个正整数,分别代表$l_i、r_i、x_i$。
【输出格式】
输出到文件 `duliu.out` 中。
输出 $m$ 行,每行一个整数,代表$min\{max_{a_i \le j \le b_i}\{d_j\}\}$,若没有合法区间,则输出$-1$。
【样例输入一】
5 2
1 1 2 3 4
1 5 2
1 5 11
【样例输出一】
1
2
【样例输入二】
5 4
1 3 2 4 6
1 3 3
1 3 2
2 4 10
1 1 1556528051
【样例输出二】
2
1
3
-1
【数据范围与提示】
保证,$n,m \le 3 \times 10^5,d_i \le 10^7,1 \le l_i \le r_i \le n,x_i \le 10^{18}$。
题解
毒瘤题目,区间价值和是 $ w=sum*len*2 $,而不是 $ sum*len $,$ j $ 不小于 $ k $
对于以 $ l $ 为起点和以 $ r $ 为结尾的区间,可以直接二分+ RMQ 解决
对于在中间的区间,显然是一个三维偏序,可以整体二分解决
然而本题卡常
记中间的区间为 $ [l_i,r_i] $,和为 $ w_i $
可以发现,当 $ r_i>r $ 时,答案显然没有以 $ r $ 为结尾的区间优,于是就转化为二维偏序,求满足 $ l_i \geq L,w_i \geq x_i $ 的区间中最大值最小
对于一个 $ a_i $,可以预处理出最大值为 $ a_i $ 的区间及它的 $ w_i $
将询问按 $ x_i $,区间按 $ w_i $ 从大到小排序,满足 $ w_i>=x_i $
将 $ a_i $ 记录到以位置为下标的线段树的 $ l_i $ 上,查询的时候只要查询 $ [L,P_r] $ 的最小值即可($ P_r $ 为以 $ r $ 为结尾的区间的左端点)
时间效率:$ O(n \log n) $
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 #define LL long long 3 #define _(d) while(d(isdigit(ch=getchar()))) 4 using namespace std; 5 LL R(){ 6 LL x;bool f=1;char ch;_(!)if(ch=='-')f=0;x=ch^48; 7 _()x=(x<<3)+(x<<1)+(ch^48);return f?x:-x;} 8 const int N=3e5+5; 9 int n,m,a[N],st[N][22],lg,tr[N<<2],tot,ans[N]; 10 LL sum[N]; 11 struct node{int x,id;}s[N]; 12 struct pig{int l,r,x;LL w;}p[N],q[N]; 13 bool cmp(node a,node b){return a.x>b.x;} 14 bool cmp2(pig a,pig b){return a.w>b.w;} 15 set<int> h; 16 set<int>::iterator it; 17 #define ls rt<<1 18 #define rs rt<<1|1 19 void update(int rt,int l,int r,int x,int v){ 20 if(l==r){tr[rt]=min(tr[rt],v);return;} 21 int mid=(l+r)>>1; 22 if(x<=mid)update(ls,l,mid,x,v); 23 else update(rs,mid+1,r,x,v); 24 tr[rt]=min(tr[ls],tr[rs]); 25 return; 26 } 27 int query(int rt,int l,int r,int ql,int qr){ 28 if(ql<=l&&qr>=r)return tr[rt]; 29 int mid=(l+r)>>1,ans=1e9; 30 if(ql<=mid)ans=query(ls,l,mid,ql,qr); 31 if(qr>mid)ans=min(ans,query(rs,mid+1,r,ql,qr)); 32 return ans; 33 } 34 int rmq(int l,int r){ 35 int x=log2(r-l+1); 36 return max(st[l][x],st[r-(1<<x)+1][x]); 37 } 38 int main(){ 39 n=R(),m=R(),lg=log2(n)+1; 40 for(int i=1;i<=n;i++) 41 sum[i]=(st[i][0]=a[i]=R())+sum[i-1],s[i]=(node){a[i],i}; 42 sort(s+1,s+1+n,cmp); 43 h.insert(0),h.insert(n+1); 44 for(int i=1,l,r;i<=n;i++){ 45 it=h.lower_bound(s[i].id); 46 r=*it-1,it--,l=*it+1; 47 p[i]=(pig){l,r,s[i].x,(sum[r]-sum[l-1])*(r-l+1)*2}; 48 h.insert(s[i].id); 49 } 50 for(int i=1;i<=m;i++){ 51 int l=R(),r=R();LL w=R(); 52 if((sum[r]-sum[l-1])*(r-l+1)*2<w)ans[i]=-1; 53 else q[++tot]=(pig){l,r,i,w}; 54 } 55 sort(p+1,p+1+n,cmp2),sort(q+1,q+1+tot,cmp2); 56 memset(tr,0x3f,sizeof tr); 57 for(int i=1;i<=lg;i++) 58 for(int j=1;j+(1<<i)-1<=n;j++) 59 st[j][i]=max(st[j][i-1],st[j+(1<<(i-1))][i-1]); 60 for(int i=1,j=1;i<=tot;i++){ 61 int l=q[i].l,r=q[i].r,res=0; 62 while(l<=r){ 63 int mid=(l+r)>>1; 64 if((sum[mid]-sum[q[i].l-1])*(mid-q[i].l+1)*2<q[i].w) l=mid+1; 65 else r=mid-1,res=mid; 66 } 67 ans[q[i].x]=rmq(q[i].l,res); 68 l=q[i].l,r=q[i].r,res=0; 69 while(l<=r){ 70 int mid=l+r>>1; 71 if((sum[q[i].r]-sum[mid-1])*(q[i].r-mid+1)*2<q[i].w) r=mid-1; 72 else l=mid+1,res=mid; 73 } 74 ans[q[i].x]=min(ans[q[i].x],rmq(res,q[i].r)); 75 while(j<=n&&p[j].w>q[i].w) update(1,1,n,p[j].l,p[j].x),j++; 76 ans[q[i].x]=min(ans[q[i].x],query(1,1,n,q[i].l,res)); 77 } 78 for(int i=1;i<=m;i++)printf("%d\n",ans[i]); 79 return 0; 80 }