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 }

  

原文地址:https://www.cnblogs.com/Suki-Sugar/p/14044381.html