BZOJ 1047 [HAOI2007]理想的正方形 单调队列DP

题解:

刚睡醒写的,总是看不清括号。。。调了半天。。

就是横向一个掉队列,纵向b个单调队列,n^2的求出以(i,j)点为右下角的n*n矩形的最大值和最小值,然后n^2的统计就好~

 

 

View Code
 1 #include <iostream>

 2 #include <cstring>

 3 #include <cstdlib>

 4 #include <cstdio>

 5 #include <algorithm>

 6 

 7 #define N 1111

 8 #define BUG system("pause")

 9 

10 using namespace std;

11 

12 long long a,b,n;

13 long long map[N][N];

14 long long q[N][N],h[N],t[N],s,e,dq[N];

15 long long mx[N][N],ans,mn[N][N];

16 

17 inline void read()

18 {

19     scanf("%lld%d%d",&a,&b,&n);

20     for(long long i=1;i<=a;i++)

21         for(long long j=1;j<=b;j++)

22             scanf("%lld",&map[i][j]);

23 }

24 

25 inline void getmax()

26 {

27     for(long long i=1;i<=b;i++) h[i]=1,t[i]=0;

28     for(long long i=1;i<=a;i++)

29     {

30         for(long long j=1;j<=b;j++)

31         {

32             

33             while(h[j]<=t[j]&&i-q[j][h[j]]+1>n) h[j]++;

34             while(h[j]<=t[j]&&map[q[j][t[j]]][j]<=map[i][j]) t[j]--;

35             q[j][++t[j]]=i;    

36         }

37         e=0; s=1;

38         for(long long j=1;j<=b;j++)

39         {

40             while(s<=e&&j-dq[s]+1>n) s++;

41             while(s<=e&&map[q[dq[e]][h[dq[e]]]][dq[e]]<=map[q[j][h[j]]][j]) e--;

42             dq[++e]=j;

43             mx[i][j]=map[q[dq[s]][h[dq[s]]]][dq[s]];

44         }

45     }

46 }

47 

48 inline void getmin()

49 {

50     for(long long i=1;i<=b;i++) h[i]=1,t[i]=0;

51     for(long long i=1;i<=a;i++)

52     {

53         for(long long j=1;j<=b;j++)

54         {

55             while(h[j]<=t[j]&&i-q[j][h[j]]+1>n) h[j]++;

56             while(h[j]<=t[j]&&map[q[j][t[j]]][j]>=map[i][j]) t[j]--;

57             q[j][++t[j]]=i;    

58         }

59         e=0; s=1;

60         for(long long j=1;j<=b;j++)

61         {

62             while(s<=e&&j-dq[s]+1>n) s++;

63             while(s<=e&&map[q[dq[e]][h[dq[e]]]][dq[e]]>=map[q[j][h[j]]][j]) e--;

64             dq[++e]=j;

65             mn[i][j]=map[q[dq[s]][h[dq[s]]]][dq[s]];

66         }

67     }

68 }

69 

70 inline void go()

71 {

72     getmin();

73     getmax();

74     ans=1LL<<60;

75     for(long long i=n;i<=a;i++)

76         for(long long j=n;j<=b;j++)

77             ans=min(ans,mx[i][j]-mn[i][j]);

78     printf("%lld\n",ans);

79 }

80 

81 int main()

82 {

83     read(),go();

84     return 0;

85 }

 

 

你可能感兴趣的:(2007)