zoukankan      html  css  js  c++  java
  • [单调栈专题]

    https://vjudge.net/contest/296911#overview

    A - Subsequence

     
    There is a sequence of integers. Your task is to find the longest subsequence that satisfies the following condition: the difference between the maximum element and the minimum element of the subsequence is no smaller than m and no larger than k.

    Input

    There are multiple test cases. 
    For each test case, the first line has three integers, n, m and k. n is the length of the sequence and is in the range [1, 100000]. m and k are in the range [0, 1000000]. The second line has n integers, which are all in the range [0, 1000000]. 
    Proceed to the end of file. 
    Output

    For each test case, print the length of the subsequence on a single line.

    Sample Input

    5 0 0
    1 1 1 1 1
    5 0 3
    1 2 3 4 5

    Sample Output

    5
    4
    题意:求满足区间内最大元素值-最小元素值>=m&&<=k的最长区间长度
    题解:两个单调栈,一个栈维护一个递增序列,另一个栈维护一个递减序列,通过二者差值<=k移动head指针,然后检查是否>=m更新ans
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<queue>
     5 #include<set>
     6 #include<map>
     7 #include<stack>
     8 #include<vector>
     9 #include<cmath>
    10 #include<algorithm>
    11 using namespace std;
    12 typedef long long ll;
    13 #define debug(x,y,z) cout<< #x <<" is "<<x<<" "<< #y <<" is "<<y<<" "<< #z <<" is "<<z<<endl;
    14 #define debugs(x) cout<< #x <<" is "<<x<<endl;
    15 const ll inf=1e10;
    16 ll a[100005];
    17 int q[100005],w[100005];
    18 int main()
    19 {
    20     int n,m,k;
    21     while(scanf("%d",&n)==1){
    22         scanf("%d%d",&m,&k);
    23         for(int i=1;i<=n;i++){
    24             scanf("%lld",&a[i]);
    25         }
    26         int ans=0;
    27         int head,tail,head2,tail2;
    28         head=1;
    29         tail=0;
    30         head2=1;
    31         tail2=0;
    32         int pre=1;
    33         for(int i=1;i<=n;i++){
    34             while(tail>=head&&a[q[tail]]>a[i])tail--;
    35             while(tail2>=head2&&a[w[tail2]]<a[i])tail2--;
    36             q[++tail]=i;
    37             w[++tail2]=i;
    38             while(head<=tail&&head2<=tail2&&a[w[head2]]-a[q[head]]>k){
    39                 if(q[head]<w[head2]){
    40                     pre=q[head++]+1;
    41                 }
    42                 else{
    43                     pre=w[head2++]+1;
    44                 }
    45             }
    46             if(a[w[head2]]-a[q[head]]<=k&&a[w[head2]]-a[q[head]]>=m){
    47                 ans=max(ans,i-pre+1);
    48             }
    49            // debugs(w[head2]);
    50            // debugs(q[head]);
    51         }
    52         printf("%d
    ",ans);
    53     }
    54     return 0;
    55 }
    View Code

    B - Second My Problem First

    Give you three integers n, A and B. 
    Then we define S i = A i mod B and T i = Min{ S k | i-A <= k <= i, k >= 1} 
    Your task is to calculate the product of T i (1 <= i <= n) mod B.

    Input

    Each line will contain three integers n(1 <= n <= 10 7),A and B(1 <= A, B <= 2 31-1). 
    Process to end of file.

    Output

    For each case, output the answer in a single line.

    Sample Input

    1 2 3
    2 3 4
    3 4 5
    4 5 6
    5 6 7

    Sample Output

    2
    3
    4
    5
    6

     题意: S i = A i mod B ,T i = Min{ S k | i-A <= k <= i, k >= 1} ,求Ti(1<=i<=n)乘积%B的结果

    题解:水题。直接维护一个单调栈即可线性求出所有Ti

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<queue>
     5 #include<set>
     6 #include<map>
     7 #include<stack>
     8 #include<vector>
     9 #include<cmath>
    10 #include<algorithm>
    11 using namespace std;
    12 typedef long long ll;
    13 #define debug(x,y,z) cout<< #x <<" is "<<x<<" "<< #y <<" is "<<y<<" "<< #z <<" is "<<z<<endl;
    14 #define debugs(x) cout<< #x <<" is "<<x<<endl;
    15 int a[10000005],b[10000005];
    16 int main()
    17 {
    18     ll n,A,B;
    19     while(scanf("%lld%lld%lld",&n,&A,&B)==3){
    20         a[0]=1;
    21         for(int i=1;i<=n;i++)a[i]=a[i-1]*A%B;
    22         int head=1;
    23         int tail=0;
    24         ll ans=1;
    25         for(int i=1;i<=n;i++){
    26             while(head<=tail&&a[b[tail]]>=a[i])tail--;
    27             b[++tail]=i;
    28             while(head<=tail&&(b[head])<(i-A))head++;
    29             ans=ans*a[b[head]]%B;
    30         }
    31         printf("%lld
    ",ans);
    32     }
    33     return 0;
    34 }
    View Code

    D - Largest Rectangle in a Histogram

    A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rectangles have equal widths but may have different heights. For example, the figure on the left shows the histogram that consists of rectangles with the heights 2, 1, 4, 5, 1, 3, 3, measured in units where 1 is the width of the rectangles: 

    Usually, histograms are used to represent discrete distributions, e.g., the frequencies of characters in texts. Note that the order of the rectangles, i.e., their heights, is important. Calculate the area of the largest rectangle in a histogram that is aligned at the common base line, too. The figure on the right shows the largest aligned rectangle for the depicted histogram.

    Input

    The input contains several test cases. Each test case describes a histogram and starts with an integer n, denoting the number of rectangles it is composed of. You may assume that 1<=n<=100000. Then follow n integers h1,...,hn, where0<=hi<=1000000000. These numbers denote the heights of the rectangles of the histogram in left-to-right order. The width of each rectangle is 1. A zero follows the input for the last test case.

    Output

    For each test case output on a single line the area of the largest rectangle in the specified histogram. Remember that this rectangle must be aligned at the common base line.

    Sample Input

    7 2 1 4 5 1 3 3
    4 1000 1000 1000 1000
    0
    

    Sample Output

    8
    4000
    

    Hint

    Huge input, scanf is recommended.
    题意:给出各个矩形的高度,求出合并后最大的矩形面积
    题解:枚举高度的最小值(即枚举最低矩形的编号),然后正向维护一个单调栈反向维护一个单调栈即可求出矩形长,长*宽即可
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<queue>
     5 #include<set>
     6 #include<map>
     7 #include<stack>
     8 #include<vector>
     9 #include<cmath>
    10 #include<algorithm>
    11 using namespace std;
    12 typedef long long ll;
    13 #define debug(x,y,z) cout<< #x <<" is "<<x<<" "<< #y <<" is "<<y<<" "<< #z <<" is "<<z<<endl;
    14 #define debugs(x) cout<< #x <<" is "<<x<<endl;
    15 ll a[100005],b[100005],c[100005],d[100005];
    16 int main()
    17 {
    18     int n;
    19     while(scanf("%d",&n)&&n){
    20         for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    21         int tot=0;
    22         b[0]=0;
    23         for(int i=1;i<=n;i++){
    24             while(tot&&a[b[tot]]>=a[i])tot--;
    25             c[i]=b[tot]+1;
    26             b[++tot]=i;
    27         }
    28         b[0]=n+1;
    29         tot=0;
    30         for(int i=n;i>=1;i--){
    31             while(tot&&a[b[tot]]>=a[i])tot--;
    32             d[i]=b[tot]-1;
    33             b[++tot]=i;
    34         }
    35         ll ans=0;
    36         for(int i=1;i<=n;i++){
    37             ans=max(ans,(d[i]-c[i]+1)*a[i]);
    38         }
    39         printf("%lld
    ",ans);
    40     }
    41     return 0;
    42 }
    View Code

    E - Queue

    There are n walruses standing in a queue in an airport. They are numbered starting from the queue's tail: the 1-st walrus stands at the end of the queue and the n-th walrus stands at the beginning of the queue. The i-th walrus has the age equal to ai.

    The i-th walrus becomes displeased if there's a younger walrus standing in front of him, that is, if exists such j (i < j), that ai > aj. The displeasure of the i-th walrus is equal to the number of walruses between him and the furthest walrus ahead of him, which is younger than the i-th one. That is, the further that young walrus stands from him, the stronger the displeasure is.

    The airport manager asked you to count for each of n walruses in the queue his displeasure.

    Input

    The first line contains an integer n (2 ≤ n ≤ 105) — the number of walruses in the queue. The second line contains integers ai (1 ≤ ai ≤ 109).

    Note that some walruses can have the same age but for the displeasure to emerge the walrus that is closer to the head of the queue needs to be strictly younger than the other one.

    Output

    Print n numbers: if the i-th walrus is pleased with everything, print "-1" (without the quotes). Otherwise, print the i-th walrus's displeasure: the number of other walruses that stand between him and the furthest from him younger walrus.

    Examples

    Input
    6
    10 8 5 3 50 45
    Output
    2 1 0 -1 0 -1 
    Input
    7
    10 4 6 3 2 8 15
    Output
    4 2 1 0 -1 -1 -1 
    Input
    5
    10 3 1 10 11
    Output
    1 0 -1 -1 -1 
    题意:求出对于每个元素来说在自己右边且比自己小的元素离自己的最远距离
    题解:维护一个单调栈,然后就可以二分单调栈求出最远的比自己小的元素
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<queue>
     5 #include<set>
     6 #include<map>
     7 #include<stack>
     8 #include<vector>
     9 #include<cmath>
    10 #include<algorithm>
    11 using namespace std;
    12 typedef long long ll;
    13 #define debug(x,y,z) cout<< #x <<" is "<<x<<" "<< #y <<" is "<<y<<" "<< #z <<" is "<<z<<endl;
    14 #define debugs(x) cout<< #x <<" is "<<x<<endl;
    15 int a[100005],b[100005],c[100005],d[100005];
    16 int main()
    17 {
    18     int n;
    19     scanf("%d",&n);
    20     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    21     //int head=1;
    22     int tail=0;
    23     for(int i=n;i>=1;i--){
    24         if(tail==0||-b[tail]>=a[i]){
    25             c[i]=-1;
    26             b[++tail]=-a[i];
    27             d[tail]=i;
    28         }
    29         else{
    30             int pos=upper_bound(b+1,b+1+tail,-a[i])-b;
    31             c[i]=d[pos]-i-1;
    32         }
    33     }
    34     for(int i=1;i<=n;i++){
    35         printf("%d",c[i]);
    36         char cc=(i==n)?'
    ':' ';
    37         printf("%c",cc);
    38     }
    39     return 0;
    40 }
    View Code

    F - Watching Fireworks is Fun

    A festival will be held in a town's main street. There are n sections in the main street. The sections are numbered 1 through n from left to right. The distance between each adjacent sections is 1.

    In the festival m fireworks will be launched. The i-th (1 ≤ i ≤ m) launching is on time ti at section ai. If you are at section x (1 ≤ x ≤ n) at the time of i-th launching, you'll gain happiness value bi - |ai - x| (note that the happiness value might be a negative value).

    You can move up to d length units in a unit time interval, but it's prohibited to go out of the main street. Also you can be in an arbitrary section at initial time moment (time equals to 1), and want to maximize the sum of happiness that can be gained from watching fireworks. Find the maximum total happiness.

    Note that two or more fireworks can be launched at the same time.

    Input

    The first line contains three integers nmd (1 ≤ n ≤ 150000; 1 ≤ m ≤ 300; 1 ≤ d ≤ n).

    Each of the next m lines contains integers aibiti (1 ≤ ai ≤ n; 1 ≤ bi ≤ 109; 1 ≤ ti ≤ 109). The i-th line contains description of the i-th launching.

    It is guaranteed that the condition ti ≤ ti + 1 (1 ≤ i < m) will be satisfied.

    Output

    Print a single integer — the maximum sum of happiness that you can gain from watching all the fireworks.

    Please, do not write the %lld specifier to read or write 64-bit integers in C++. It is preferred to use the cin, cout streams or the %I64d specifier.

    Examples

    Input
    50 3 1
    49 1 1
    26 1 4
    6 1 10
    Output
    -31
    Input
    10 2 1
    1 1000 4
    9 1000 4
    Output
    1992
    题意:有m种烟花,每种烟花有一个最佳观看地点ai,在x处观看烟花得到的快乐值为 bi-abs(ai-x),释放时刻为ti,你的初始位置可以是1~n的任意点,每秒可以移动d米,求欢乐值之和的最大值

     题解:设dp[i][j]表示在j处观看第i种烟花的最大值,则dp[i][j]=max(dp[i-1][k])+b[i]-abs(a[i]-j) 其中(a[i]-(t[i]-t[i-1])*d<=k<=a[i]+(t[i]-t[i-1])*d),所以可以使用单调队列加速dp

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<queue>
     5 #include<set>
     6 #include<map>
     7 #include<stack>
     8 #include<vector>
     9 #include<cmath>
    10 #include<algorithm>
    11 using namespace std;
    12 typedef long long ll;
    13 #define debug(x,y,z) cout<< #x <<" is "<<x<<" "<< #y <<" is "<<y<<" "<< #z <<" is "<<z<<endl;
    14 #define debugs(x) cout<< #x <<" is "<<x<<endl;
    15 struct pot{
    16     ll tim;
    17     ll a;
    18     ll b;
    19 }p[305];
    20 int q[150005],w[150005];
    21 ll dp[2][150005];
    22 map<int,int>mp;
    23 const ll inf=1e18;
    24 int main()
    25 {
    26     int n,m,d;
    27     scanf("%d%d%d",&n,&m,&d);
    28     int tot=0;
    29     for(int i=1;i<=m;i++){
    30         scanf("%I64d%I64d%I64d",&p[i].a,&p[i].b,&p[i].tim);
    31         if(!mp[p[i].tim])mp[p[i].tim]=++tot;
    32     }
    33     ll ans=-inf;
    34     int t=-1;
    35     int id=0;
    36     for(int i=1;i<=m;i++){
    37         int head=1;
    38         int tail=0;
    39         int k=1;
    40         if(p[i].tim==t){
    41             for(int j=1;j<=n;j++){
    42                 dp[id][j]=dp[id^1][j]+p[i].b-abs(p[i].a-j);
    43             }
    44         }
    45         else{
    46             for(int j=1;j<=n;j++){
    47                 dp[id][j]=-inf;
    48                 while(k<=n&&k<=j+(p[i].tim-t)*d){
    49                     while(head<=tail&&dp[id^1][k]>dp[id^1][q[tail]])tail--;
    50                     q[++tail]=k;
    51                     k++;
    52                 }
    53                 while(head<=tail&&q[head]<j-(p[i].tim-t)*d)head++;
    54                 if(head<=tail)dp[id][j]=dp[id^1][q[head]]+p[i].b-abs(p[i].a-j);
    55             }
    56             t=p[i].tim;
    57         }
    58         id^=1;
    59     }
    60     for(int i=1;i<=n;i++){
    61       //  debugs(dp[m][i]);
    62         ans=max(dp[id^1][i],ans);
    63     }
    64     printf("%I64d
    ",ans);
    65     return 0;
    66 }
    View Code
  • 相关阅读:
    虎虎的小尾巴:期货套利的入门——全文干货(2020-05-10)
    虎虎的小尾巴:对化工板块的一些思考(2020-05-06)
    虎虎的小尾巴:本周小结(2020-04-30)
    虎虎的小尾巴:耐得住寂寞,经得住诱惑(2020-04-24)
    虎虎的小尾巴:first blood(2020-04-19)
    虎虎的小尾巴:财不入急门(2020-04-15)
    虎虎的小尾巴:再谈仓位管理的重要性(2020-04-7)
    学习Linux系列--布署常用服务
    学习Linux系列--安装软件环境
    Asp.Net运行于32/64模式下的性能差异
  • 原文地址:https://www.cnblogs.com/MekakuCityActor/p/10759387.html
Copyright © 2011-2022 走看看