hdu 5289 Assignment(2015多校第一场第2题)RMQ+二分(或者multiset模拟过程)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5289

题意:给你n个数和k,求有多少的区间使得区间内部任意两个数的差值小于k,输出符合要求的区间个数

思路:求出区间的最大最小值,只要他们的差值小于k,那么这个区间就符合要求,但是由于n较大,用暴力一定超时,所以就要用别的方法了;而RMQ是可以求区间的最值的,而且预处理的复杂度只有O(nlogn),而查询只是O(1)处理,这样相对来说节约了时间,再根据右端点来二分枚举左端点(其实不用二分好像更快,估计是数据问题)。

而另一种方法不得不说,学了C++的一定要在认真的去看一下STL的那些用法,这次用multiset来做就大大的节约时间,而且又不用思考太多,只要从左到右模拟区间,就可以了。

(RMQ+二分)代码:

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <iostream>
 6 #include <queue>
 7 #include <algorithm>
 8 #include <vector>
 9 #include <set>
10 using namespace std;
11 #define LL __int64
12 #define INF 0x3f3f3f3f
13 const int MAXN=100005;
14 #define mod 1000000007
15
16 int a[MAXN];
17 LL ans;
18 int dp1[MAXN][30],dp2[MAXN][30];
19
20 void init(int n)
21 {
22     for(int i=1;i<=n;i++)
23         dp1[i][0]=dp2[i][0]=a[i];
24     for(int j=1;(1<<j)<=n;j++)
25     {
26         for(int i=1;i+(1<<j)-1<=n;i++)
27         {
28             dp1[i][j]=max(dp1[i][j-1],dp1[i+(1<<(j-1))][j-1]);
29             dp2[i][j]=min(dp2[i][j-1],dp2[i+(1<<(j-1))][j-1]);
30         }
31     }
32 }
33
34 int RMQ(int L,int R)
35 {
36     int k=0;
37     while((1<<(k+1))<=R-L+1)k++;
38     return max(dp1[L][k],dp1[R-(1<<k)+1][k])-min(dp2[L][k],dp2[R-(1<<k)+1][k]);
39 }
40
41 int binarySearch(int L,int R,int n,int k)
42 {
43     int mid;
44     int l=L,r=R;
45     while(l<=r)
46     {
47         mid=(l+r)/2;
48         if(RMQ(mid,R)>=k)
49         {
50             l=mid+1;
51         }
52         else
53         {
54             r=mid-1;
55         }
56     }
57     if(RMQ(mid,R)>=k)
58         mid++;
59     return mid;
60 }
61 int main()
62 {
63     int T,i,j,n,k,mi,ma,l,r;
64     while(~scanf("%d",&T))
65     {
66         while(T--)
67         {
68             scanf("%d%d",&n,&k);
69             for(i=1;i<=n;i++)
70                 scanf("%d",&a[i]);
71             if(!k)
72             {
73                 printf("0\n");
74                 continue;
75             }
76             if(k==1)
77             {
78                 printf("%d\n",n);
79                 continue;
80             }
81             init(n);
82             ans=0;
83             for(i=j=1;i<=n;i++)
84             {
85                 j=binarySearch(j,i,n,k);
86                 ans+=i-j+1;
87             }
88             printf("%I64d\n",ans);
89         }
90     }
91     return 0;
92 }

(STL)代码:

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <iostream>
 6 #include <queue>
 7 #include <algorithm>
 8 #include <vector>
 9 #include <set>
10 using namespace std;
11 #define LL __int64
12 #define INF 0x3f3f3f3f
13 const int MAXN=100005;
14 #define mod 1000000007
15
16 int a[100005];
17 LL ans;
18 int main()
19 {
20     int T,i,j,n,k,mi,ma,l,r;
21     while(~scanf("%d",&T))
22     {
23         while(T--)
24         {
25             scanf("%d%d",&n,&k);
26             for(i=0;i<n;i++)
27                 scanf("%d",&a[i]);
28             if(!k)
29             {
30                 printf("0\n");
31                 continue;
32             }
33             if(k==1)
34             {
35                 printf("%d\n",n);
36                 continue;
37             }
38             l=0;
39             r=1;
40             multiset<int>s;
41             s.insert(a[0]);
42             ans=n;
43             while(1)
44             {
45                 if(s.size())
46                 {
47                     mi=*s.begin();
48                     ma=*s.rbegin();
49                     if(abs(a[r]-mi)<k&&abs(a[r]-ma)<k)
50                     {
51                         ans+=s.size();
52                         s.insert(a[r]);
53                         r++;
54                         if(r==n)
55                             break;
56                     }
57                     else
58                     {
59                         if(s.size())
60                             s.erase(s.find(a[l]));
61                         l++;
62                     }
63                 }
64                 else
65                 {
66                     l=r;
67                     s.insert(a[r]);
68                     r++;
69                     if(r==n)
70                         break;
71                 }
72             }
73             printf("%I64d\n",ans);
74         }
75     }
76     return 0;
77 }

时间: 2024-10-11 13:37:24

hdu 5289 Assignment(2015多校第一场第2题)RMQ+二分(或者multiset模拟过程)的相关文章

HDU 5289 Assignment(2015 多校第一场二分 + RMQ)

Assignment Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 627    Accepted Submission(s): 318 Problem Description Tom owns a company and he is the boss. There are n staffs which are numbered fr

hdu 5294 Tricks Device(2015多校第一场第7题)最大流+最短路

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5294 题意:给你n个墓室,m条路径,一个人在1号墓室(起点),另一个人在n号墓室(终点),起点的那个人只有通过最短路径才能追上终点的那个人,而终点的那个人能切断任意路径. 第一问--终点那人要使起点那人不能追上的情况下可以切的最少的路径数,输出最少的路径数 第二问--起点那人能追上终点那人的情况下,终点那人能切断的最多的路径数,输出最多的路径数 思路:要使起点那人无法追上,只要使他的最短路径不存在就

hdu 5288 OO’s Sequence(2015多校第一场第1题)枚举因子

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5288 题意:在闭区间[l,r]内有一个数a[i],a[i]不能整除 除去自身以外的其他的数,f(l,r)表示在这区间内a[i]这样的数的个数,,现给你n个数,求所有区间的f(l,r)的和. 思路:对于每个数a[i]求出他的左右侧最靠近他的且是他的因子的位置L.R,并记录,那么对于每个数a[i]都有了他的L,R,而对于每个a[i]在f(l,r)有价值的次数之和就是(i-L+1)*(R-i+1) 代码:

hdu 5308 (2015多校第二场第9题)脑洞模拟题,无语

题目链接:http://acm.hdu.edu.cn/listproblem.php?vol=44 题意:给你n个n,如果能在n-1次运算之后(加减乘除)结果为24的输出n-1次运算的过程,如果不能输出-1. 思路:乍看起来,没什么规律,但是可以想象的是(n+n+n+n)/n=4,(n+n+n+n+n+n)/n=6,(n-n)*n*n*·····*n=0所以在n大于15的时候结果基本是固定的,只要对小于15的数一一输出就行(但是这题真是无语,算这种题目真是累,脑洞啊~~) 代码: 1 #incl

hdu 5301 Buildings (2015多校第二场第2题) 简单模拟

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5301 题意:给你一个n*m的矩形,可以分成n*m个1*1的小矩形,再给你一个坐标(x,y),表示黑格子在n*m矩形中的位置,黑格子占一个1*1的小矩形的空间,用各种矩形去填充n*m矩形,(x,y)位置不能填,且每个去填充的小矩形都有一边是靠着n*m矩形的外框,求这些填充的小矩形在最小大小情况下的面积最大的矩形面积. 思路:要是填充的矩形大小最小,那么靠近边框的长度一定为1,所以只要判断在矩形内部的长

HDU 5288 OO&#39;s sequence (2015多校第一场 二分查找)

OO's Sequence Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 955    Accepted Submission(s): 358 Problem Description OO has got a array A of size n ,defined a function f(l,r) represent the nu

HDU 5289 Assignment(多校联合第一场1002)

Assignment Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 617    Accepted Submission(s): 314 Problem Description Tom owns a company and he is the boss. There are n staffs which are numbered fr

HDU 5289 Assignment(多校2015 RMQ 单调(双端)队列)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5289 Problem Description Tom owns a company and he is the boss. There are n staffs which are numbered from 1 to n in this company, and every staff has a ability. Now, Tom is going to assign a special tas

hdu 5305 Friends(2015多校第二场第6题)记忆化搜索

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5305 题意:给你n个人,m条关系,关系可以是online也可以是offline,让你求在保证所有人online关系的朋友和offline关系的朋友相等的情况下,这样的情况有多少种. 思路:因为online关系和offline关系的人数相等,而且m最多才28,所以只要枚举每个人的一半的关系是否符合要求即可,而且根据题意m是奇数或者有一个人的总关系为奇数那么就没有符合要求的情况,这样可以排除很多情况.