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+二分)代码:

hdu 5289 Assignment(2015多校第一场第2题)RMQ+二分(或者multiset模拟过程)
 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 }
View Code

(STL)代码:

hdu 5289 Assignment(2015多校第一场第2题)RMQ+二分(或者multiset模拟过程)
 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 }
View Code

 

你可能感兴趣的:(sign)