标签:log algo main nbsp queue getc std 题目 out
dp[i]表示前i棵树的最小体力消耗值
但是如果直接上肯定时间复杂度会爆炸 (N*Q*K)
N和Q已经无法优化
所以需要优化k 通过一种数据结构找到 k个位置中最合适的位置 从而达到N*Q的时间复杂度
线段树和树状数组略有吃力,所以需要根据题目的单调性需要单调队列。
什么情况需要优化呢?
1.当前的位置dp值相等 但比之前的k个数的中某个数大 那肯定保留大的
2.如果dp值不相等 肯定保留小的那个位置
代码实现前仔细思考!!!!
1 #include <cstdio> 2 #include <queue> 3 #include <algorithm> 4 #include <cstring> 5 6 inline int Read(){ 7 int x = 0,f = 1; 8 char ch = getchar(); 9 while(ch < ‘0‘ || ch >‘9‘){ 10 if(ch==‘-‘) f = -1; 11 ch = getchar(); 12 } 13 while(ch >= ‘0‘ && ch <= ‘9‘){ 14 x = x*10 + ch - ‘0‘; 15 ch = getchar(); 16 } 17 return x*f; 18 } 19 20 int dp[1000005],num[1000005]; 21 int n,m; 22 std::deque<int>Q; 23 24 int GetOut(int k){ 25 memset(dp,0x3f3f3f3f,sizeof(dp)); 26 Q.clear(); 27 Q.push_back(1); 28 dp[1]=0; 29 for(int i=2;i<=n;i++){ 30 //printf("fuck\n"); 31 while(!Q.empty() && Q.front() < i - k) Q.pop_front(); 32 dp[i] = dp[Q.front()] + (num[i] >= num[Q.front()]); 33 //printf("fuck\n"); 34 while( !Q.empty() ){ 35 if(dp[i] == dp[Q.back()]){ 36 if(num[i] > num[Q.back()]){ 37 Q.pop_back(); 38 } 39 else break; 40 } 41 else{ 42 if(dp[i] < dp[Q.back()]){ 43 Q.pop_back(); 44 } 45 else break; 46 } 47 } 48 Q.push_back(i); 49 //printf("%d\n",i); 50 } 51 return dp[n]; 52 } 53 54 void init(){ 55 n = Read(); 56 for(int i=1;i<=n;i++){ 57 num[i] = Read(); 58 } 59 m = Read(); 60 for(int i=1;i<=m;i++){ 61 printf("%d\n",GetOut( Read() )); 62 } 63 return; 64 } 65 66 int main(){ 67 init(); 68 return 0; 69 }
标签:log algo main nbsp queue getc std 题目 out
原文地址:http://www.cnblogs.com/OIerLYF/p/7496017.html