zoukankan      html  css  js  c++  java
  • Codeforces Round #686 (Div. 3) F

    题目传送门

    借鉴大佬博客 :https://blog.csdn.net/qq_45458915/article/details/110138103

    题意:

      将给定数组分成 x y z 长度的三部分,并满足 max(1,x)=min(x+1,x+y)=max(x+y+1,n) ,输出任意一组满足题意的x y z;如果不存在,输出"NO;

    思路:

      处理区间最值直接上线段树,重点是处理区间长度分配问题。

      枚举遍历 x 断点不可避免,如果也去朴素的遍历断点 y ,时间复杂度将爆炸(我自己想到这里就崩了,大佬的二分是真的秒,老蒟蒻了)

      随着区间的增大 ,区间最大值递增不减 , 区间最小值递减不增

      设第一段区间最大值 f1,中间区间的最小值 fMin ,第三段区间的最大值 f2; // 以下区间均指中间区间

      1. f1 > fMin   区间需减小(使 fMin 尽可能变大),   r=mid-1;

      2. f1 < fMin   区间需增大 (使 fMin 尽可能减小),  l=mid+1;

      3. f1 > f2  区间需减小 (使 f2 尽可能增大),   r=mid-1;

      4. f1 < f2  区间需增大 (使 f2 尽可能减小),   l=mid+1; 

     1 #include<bits/stdc++.h>
     2 #define db double
     3 using namespace std;
     4 typedef long long ll;
     5 const int inf =0x3f3f3f3f;
     6 const int qs =2e5+7;
     7 struct node{
     8     int Min,Max;
     9 };
    10 struct Tree{
    11     int Max,Min,l,r;
    12 }t[qs*4];
    13 int n,T,A[qs];
    14 void build(int p,int l,int r){
    15     t[p].l=l; t[p].r=r;
    16     if(l==r){
    17         t[p].Max=t[p].Min=A[l];
    18         return ;
    19     }
    20     int mid=(l+r)>>1;
    21     build(p*2,l,mid);
    22     build(p*2+1,mid+1,r);
    23     t[p].Max=max(t[p*2].Max,t[p*2+1].Max);
    24     t[p].Min=min(t[p*2].Min,t[p*2+1].Min);
    25 }
    26 node ask(int p,int l,int r){
    27     if(l<=t[p].l&&r>=t[p].r){
    28         node b;
    29         b.Max=t[p].Max;
    30         b.Min=t[p].Min;
    31         return b;
    32     }
    33     int mid=(t[p].l+t[p].r)>>1;
    34     node f;
    35     f.Min=inf,f.Max=-1;
    36     if(l<=mid){
    37         node a=ask(p*2,l,r);
    38         f.Min=min(f.Min,a.Min);
    39         f.Max=max(f.Max,a.Max);
    40     }
    41     if(r>mid){
    42         node a=ask(p*2+1,l,r);
    43         f.Max=max(a.Max,f.Max);
    44         f.Min=min(f.Min,a.Min);
    45     }
    46     return f;
    47 }
    48 void solve(){
    49     int mid;
    50     for(int i=1;i<n-1;++i){
    51         int l=i+1,r=n-1;
    52         node f;
    53         f=ask(1,1,i);
    54         int f1=f.Max;
    55         while(l<=r){
    56             mid=(l+r)>>1;
    57             f=ask(1,i+1,mid);
    58             int fMin=f.Min;
    59             f=ask(1,mid+1,n);
    60             int f3=f.Max;
    61             if(f1>fMin||f1>f3) r=mid-1;
    62             else if(f1<fMin||f1<f3) l=mid+1;
    63             else{
    64                 printf("YES
    ");
    65                 printf("%d %d %d
    ",i,mid-i,n-mid);
    66                 return;
    67             }
    68         }
    69     }
    70     puts("NO");
    71 }
    72 int main(){
    73     std::ios::sync_with_stdio(false);
    74     cin>>T;
    75     while(T--){
    76         cin>>n;
    77         for(int i=1;i<=n;++i) cin>>A[i];
    78         build(1,1,n);
    79         solve();
    80     }    
    81     return 0;
    82 }

      

  • 相关阅读:
    【leetcode】三维形体投影面积
    【leetcode】区域和检索
    【leetcode】二叉搜索树的范围和
    【leetcode】数组序号转换
    【leetcode】赎金信
    【leetcode】矩形重叠
    【leetcode】转变日期格式
    053-158
    053-268
    053-160
  • 原文地址:https://www.cnblogs.com/Suki-Sugar/p/14044381.html
Copyright © 2011-2022 走看看