sdut 1452 选美大赛 单调队列

http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=1452

题目:中文.....

思路:

单调队列维护最大最小,st记录起始位置,如果出现st到i的最大最小差值大于k,要么移动最大要么移动最小,我们只要移动那个坐标小的即可。

//#pragma comment(linker,"/STACK:327680000,327680000")  
#include <iostream>  
#include <cstdio>  
#include <cmath>  
#include <vector>  
#include <cstring>  
#include <algorithm>  
#include <string>  
#include <set>  
#include <functional>  
#include <numeric>  
#include <sstream>  
#include <stack>  
#include <map>  
#include <queue>  
  
#define CL(arr, val)    memset(arr, val, sizeof(arr))  
  
#define ll long long  
#define inf 0x7f7f7f7f  
#define lc l,m,rt<<1  
#define rc m + 1,r,rt<<1|1  
#define pi acos(-1.0)  
#define ll long long  
#define L(x)    (x) << 1  
#define R(x)    (x) << 1 | 1  
#define MID(l, r)   (l + r) >> 1  
#define Min(x, y)   (x) < (y) ? (x) : (y)  
#define Max(x, y)   (x) < (y) ? (y) : (x)  
#define E(x)        (1 << (x))  
#define iabs(x)     (x) < 0 ? -(x) : (x)  
#define OUT(x)  printf("%I64d\n", x)  
#define lowbit(x)   (x)&(-x)  
#define Read()  freopen("din.txt", "r", stdin)  
#define Write() freopen("dout.txt", "w", stdout);  
  
  
#define N 100007  
using namespace std;  
  
int a[N];  
int qmin[N*10],qmax[N*10];  
int ifr,itl,afr,atl;  
  
struct node  
{  
    int u,v;  
}g[N];  
int len,num;  
  
int n,k;  
  
int main()  
{  
    //Read();  
    int i;  
    while (~scanf("%d%d",&n,&k))  
    {  
        for (i = 1; i <= n; ++i) scanf("%d",&a[i]);  
  
        int len = 0;  
        ifr = afr = 0;  
        itl = atl = -1;  
        int st = 1;  
        CL(qmin,0);  
        CL(qmax,0); len = 0; num = 0;  
  
        for (i = 1; i <= n; ++i)  
        {  
            //最小
            while (ifr <= itl && a[qmin[itl]] > a[i]) itl--;  
            qmin[++itl] = i;  
            //最大
            while (afr <= atl && a[qmax[atl]] < a[i]) atl--;  
            qmax[++atl] = i;  
  
            //处理差值大于k的情况
            while (ifr <= itl && afr <= atl && a[qmax[afr]] - a[qmin[ifr]] > k)  
            {  
                //移动坐标小的那个
                if (qmax[afr] < qmin[ifr])  
                {  
                    st = qmax[afr] + 1;  
                    afr++;  
                }  
                else  
                {  
                    st = qmin[ifr] + 1;  
                    ifr++;  
                }  
            }  
            if (len < i - st + 1)  
            {  
                len = i - st + 1;  
                num = 0;  
                g[num].u = st;  
                g[num].v = i;  
                num++;  
            }  //记录最大
            else if (len == i - st + 1)  
            {  
                g[num].u = st;  
                g[num].v = i;  
                num++;  
            }  
        }  
        printf("%d %d\n",len,num);  
        for (i = 0; i < num; ++i)  
        printf("%d %d\n",g[i].u,g[i].v);  
  
  
    }  
    return 0;  
}  
   

  

 

posted @ 2013-01-28 19:44  E_star  阅读(222)  评论(0编辑  收藏  举报