标签:结构 ++ 简单 集中 namespace 有趣的 转变 struct c++
小明这些天一直在思考这样一个奇怪而有趣的问题:
在1~N的某个全排列中有多少个连号区间呢?这里所说的连号区间的定义是:
如果区间[L, R] 里的所有元素(即此排列的第L个到第R个元素)递增排序后能得到一个长度为R-L+1的“连续”数列,则称这个区间连号区间。
当N很小的时候,小明可以很快地算出答案,但是当N变大的时候,问题就不是那么简单了,现在小明需要你的帮助。
第一行是一个正整数N (1 <= N <= 50000), 表示全排列的规模。
第二行是N个不同的数字Pi(1 <= Pi <= N), 表示这N个数字的某一全排列。
输出一个整数,表示不同连号区间的数目。
1 // 两遍RMQ写法 2 #include<bits/stdc++.h> 3 using namespace std; 4 const int N = 50000 + 10; 5 int n, a[N], ma[N], mi[N], d1[N][16], d2[N][16]; 6 7 void RMQ_INIT1(){ 8 for(int i = 0; i < n; i++) d1[i][0] = a[i]; 9 for(int j = 1; (1<<j) <= n; j++) 10 for(int i = 0; i + (1<<j) -1 < n; i++) 11 d1[i][j] = min(d1[i][j-1], d1[i+(1<<(j-1))][j-1]); 12 } 13 14 void RMQ_INIT2(){ 15 for(int i = 0; i < n; i++) d2[i][0] = a[i]; 16 for(int j = 1; (1<<j) <= n; j++) 17 for(int i = 0; i + (1<<j) -1 < n; i++) 18 d2[i][j] = max(d2[i][j-1], d2[i+(1<<(j-1))][j-1]); 19 } 20 21 int query1(int L, int R){ 22 int k = 0; 23 while((1<<(k+1)) <= R-L+1) k++; 24 return min(d1[L][k], d1[R-(1<<k)+1][k]); 25 } 26 27 int query2(int L, int R){ 28 int k = 0; 29 while((1<<(k+1)) <= R-L+1) k++; 30 return max(d2[L][k], d2[R-(1<<k)+1][k]); 31 } 32 33 int main(){ 34 scanf("%d", &n); 35 for(int i = 0; i < n; i++) scanf("%d", a+i); 36 37 RMQ_INIT1(); 38 RMQ_INIT2(); 39 int ans = 0; 40 for(int i = 0; i < n-1; i++){ 41 for(int j = i+1; j < n; j++){ 42 int mini = query1(i, j), maxi = query2(i, j); 43 if(j - i == maxi - mini) ans++; 44 // printf("%d %d , %d %d\n", i, j, mini, maxi); 45 } 46 } 47 printf("%d", ans+n); 48 return 0; 49 }
1 // RMQ的非模版结构体写法,传入STL的max和min法 2 // 注意用到了typedef简化了max和min的定义 3 // template< class T > 4 // const T& max( const T& a, const T& b ); 5 #include<bits/stdc++.h> 6 using namespace std; 7 const int N = 50000 + 10; 8 int n, a[N]; 9 10 struct RMQ{ 11 typedef const int& (&type)(const int&, const int&); 12 type func; 13 int n, **d; 14 15 RMQ(type f, int size): func(f), n(size){ 16 d = new int*[n]; 17 for(int i = 0; i < n; i++) d[i] = new int[(int)(log(n)/log(2))+1]; 18 RMQ_INIT(); 19 } 20 21 ~RMQ(){ 22 delete[] d; 23 } 24 25 void RMQ_INIT(){ 26 for(int i = 0; i < n; i++) d[i][0] = a[i]; 27 for(int j = 1; (1<<j) <= n; j++) 28 for(int i = 0; i + (1<<j) - 1 < n; i++) 29 d[i][j] = func(d[i][j-1], d[i+(1<<(j-1))][j-1]); 30 } 31 32 int query(int L, int R){ 33 int k = 0; 34 while((1<<(k+1)) <= R-L+1) k++; 35 return func(d[L][k], d[R-(1<<k)+1][k]); 36 } 37 }; 38 39 int main(){ 40 scanf("%d", &n); 41 for(int i = 0; i < n; i++) scanf("%d", a+i); 42 RMQ MAX(max,n), MIN(min,n); 43 int ans = 0; 44 for(int i = 0; i < n-1; i++){ 45 for(int j = i+1; j < n; j++){ 46 int mini = MIN.query(i, j), maxi = MAX.query(i, j); 47 if(j - i == maxi - mini) ans++; 48 // printf("%d %d , %d %d\n", i, j, mini, maxi); 49 } 50 } 51 printf("%d", ans+n); 52 return 0; 53 }
1 // RMQ的模版结构体写法,传入STL的max和min法 2 // 数组a也应该单独用模版写,不过不能放在全局部分 3 #include<bits/stdc++.h> 4 using namespace std; 5 const int N = 50000 + 10; 6 int n, a[N]; 7 template<class T> 8 struct RMQ{ 9 typedef const T& (&type)(const T&, const T&); 10 type func; 11 int n; T **d; 12 13 RMQ(type f, int size): func(f), n(size){ 14 d = new T*[n]; 15 for(int i = 0; i < n; i++) d[i] = new T[(int)(log(n)/log(2))+1]; 16 RMQ_INIT(); 17 } 18 19 ~RMQ(){ 20 delete[] d; 21 } 22 23 void RMQ_INIT(){ 24 for(int i = 0; i < n; i++) d[i][0] = a[i]; 25 for(int j = 1; (1<<j) <= n; j++) 26 for(int i = 0; i + (1<<j) - 1 < n; i++) 27 d[i][j] = func(d[i][j-1], d[i+(1<<(j-1))][j-1]); 28 } 29 30 int query(int L, int R){ 31 int k = 0; 32 while((1<<(k+1)) <= R-L+1) k++; 33 return func(d[L][k], d[R-(1<<k)+1][k]); 34 } 35 }; 36 37 int main(){ 38 scanf("%d", &n); 39 for(int i = 0; i < n; i++) scanf("%d", a+i); 40 RMQ<int> MAX(max,n), MIN(min,n); 41 int ans = 0; 42 for(int i = 0; i < n-1; i++){ 43 for(int j = i+1; j < n; j++){ 44 int mini = MIN.query(i, j), maxi = MAX.query(i, j); 45 if(j - i == maxi - mini) ans++; 46 // printf("%d %d , %d %d\n", i, j, mini, maxi); 47 } 48 } 49 printf("%d", ans+n); 50 return 0; 51 }
标签:结构 ++ 简单 集中 namespace 有趣的 转变 struct c++
原文地址:http://www.cnblogs.com/misaka14522/p/6847830.html