loongint的花篮——双方向单调栈

Loongint的花篮

【Description】

Loongint要和MM结婚了。在两人的走进礼堂的红地毯两侧,需要摆一些装饰用的花篮,有一些不同高度的花篮,现在这些花篮被Loongint依照自己的美学观念编号为S1,S2,S3…Sn(两侧的花篮高度一样)。可Loongint的MM对这些花篮的摆放方式有不同的看法,她觉得满足以下条件的花篮摆放才是最好的。

如果对于区间[Si,Sj](1<=i<j<=n)中任意的花篮都比Si高且比Sj低,那么这个区间称为一个美学区间。对于所有的美学区间,其长度(定义为j-i)都必须小于等于k,如果有长度大于k的美学区间,MM就会不高兴,Loongint就会有麻烦…

【Input】

第一行为m。表示有m组测试数据。

对于每一组:

第一行n,k,分别表示花篮的数量和美学区间的最大长度。

第二行为n个数,分别表示S1,S2,S3…Sn的值。

【Output】

如果根本不存在美学区间,输出-1。

如果存在美学区间,那么如果任意区间的长度都小于等于k,那么输出最大的长度,否则输出最大长度比k大多少(MaxLength-k)。

【Sample Input】

3

4 2

5 4 3 6

4 1

6 5 4 3

4 2

1 2 3 4

【Sample Output】

1

-1

1

【Hint】

对于30%的测试数据,1<=n<=100。

对于60%的测试数据,1=<n<=5555。

对于100%的测试数据,1<=n<=100000,0<Si<=100000,1=<m<=3。

分析:

这道题的题意简述就是

求最长的区间,使区间中的元素都比左端点大,比右端点小。

说明存在单调的性质,

想到用单调栈,具体的实现其实挺难的。

其实我知道的解法有两种,

1.双方向单调栈,

2.一遍单调栈,一遍RMQ,

这里我用的是解法一。

具体的见代码中的简析。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
program baskets;
  var
    flag,i,b,j,n,kk,t,m,k,loc:longint;
    x,q,left,right,ans,len:longint;
    a:array[0..100010]of longint;
    s,w,r,l:array[0..100010]of longint;
  procedure doing;
    var
      i,j:longint;
    begin
      fillchar(a,sizeof(a),0);
      fillchar(s,sizeof(s),0);
      fillchar(w,sizeof(w),0);
      ans:=0;len:=0;b:=0;i:=0;j:=0;//初始化
      readln(n,k);
      a[0]:=maxlongint;
      a[n+1]:=-maxlongint;
      for i:=1 to n do read(a[i]);//初始化
 
      t:=1;
      s[1]:=a[1];w[1]:=1;
      for i:=2 to n+1 do
        begin
          x:=a[i];
          while (t>0)and(s[t]>=x) do
            begin
              r[w[t]]:=i-1;
              dec(t);
            end;
          inc(t);
          s[t]:=x;w[t]:=i;
        end;//正向单调栈,求出每个元素向右递增最多到哪个位置
 
      t:=1;
      s[1]:=a[n];w[1]:=n;
      for i:=n-1 downto 0 do
        begin
          x:=a[i];
          while(t>0)and(s[t]<=x) do
            begin
              l[w[t]]:=i+1;
              dec(t);
            end;
          inc(t);
          s[t]:=x;w[t]:=i;
        end;//逆向单调栈,求出每个元素向左递减最多到哪个位置
 
      for i:=1 to n do
        begin
          b:=r[i];
          for j:=b downto i do
            if l[j]<=i then
              begin
                len:=j-i;
                break;
              end;
          if len>ans then ans:=len;
          b:=l[i];
          for j:=b to i do
            if r[j]>=i then
              begin
                len:=i-j;
                break;
              end;
          if len>ans then ans:=len;
        end;
    {
    上面这部分算是比较重点的,从1到n枚举i
    对i位置的元素我进行了双向的处理,这里对正向的简单说一下,
    用b存i向右递增区间的右端点
    (注:b+1位置的元素小于等于i,这就是单调栈的作用)
    j变量从b再向左枚举,
    判断b的向左递减区间的左端点是否小于等于i,
    若是,则i~j即是i~b间最长的以i为左端点的美学区间,
    可以break一下减少循环量。
    逆向的处理道理是相同的。
    }
      if ans<=0 then writeln(-1)
        else if ans<=k then writeln(ans)
          else writeln(ans-k);//判断,输出
    end;
 
  begin
    assign(input,'baskets.in');
    reset(input);
    assign(output,'baskets.out');
    rewrite(output);
    readln(m);
    for i:=1 to m do
      doing;//对每组数据操作
    close(input);
    close(output);
  end.

posted on   codeway3  阅读(663)  评论(0编辑  收藏  举报

编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?

导航

< 2011年10月 >
25 26 27 28 29 30 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示