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; }