csu1364 Interview
对拍了一波才找到的错误,此题我用的是二分答案加倍增查询,实际上query那里我觉得仍然有缺陷,因为每一次我的查找还是在循环找到一个k使得x+2^k <= y,而错的地方也正在此地,一开始没有判断x+2^k > y,反而直接将k=y的二进制下的最大的为1的位置,以后一定要注意边界条件。
#include<cstdio> #include<cstdlib> #include<iostream> #include<string> #include<set> #include<algorithm> #include<vector> #include<queue> #include<list> #include<cmath> #include<cstring> #include<map> #include<stack> using namespace std; #define INF 0x3f3f3f3f #define maxn 2005 #define ull unsigned long long #define ll long long #define hashmod 99999839 #define mod 9997 int a[maxn]; int dp[maxn][20],p[20]; int n,k; //dp(i,j) 表示区间[i,i+2^j]中的最大值 //dp(i,j) = max(dp(i,j-1),dp(i+2^(j-1),j-1); //dp(i,j) = max(dp(i,j-1),q(i+2^(j-1)+1,i+2^j)); //如果查询[x,y]中的最大值则q(x,y) = max(dp(x,k),q(x+2^k+1,y)),x+2^k <= y,k <= log(y-x) int bitsearch(int x){ int l = 0,r = 19,mid,ans; while(l <= r){ mid = (l+r)>>1; if(p[mid] > x) r = mid - 1; else l = mid + 1,ans = mid; } return ans; } int query(int x,int y){ if(x > y) return 0; if(x == y) return a[x]; int k = bitsearch(y); while(x + p[k] > y) k--; return max(dp[x][k],query(x+p[k]+1,y)); } bool judge(int m){ int t = n / m,sum = 0; for(int i = 1;i <= t * m;i += t){ sum += query(i,i+t-1); } if(sum > k) return true; return false; } void init(){ p[0] = 1; for(int i = 1;i <= 19;++i) p[i] = p[i - 1] << 1; } int main(){ // freopen("a.in","r",stdin); // freopen("b.out","w",stdout); init(); while(~scanf("%d%d",&n,&k)){ if(n < 0 && k < 0) break; memset(dp,0,sizeof(dp)); int Max = 0; for(int i = 1;i <= n;++i) scanf("%d",&a[i]),dp[i-1][0] = max(a[i-1],a[i]),Max = max(Max,a[i]); dp[n][0] = a[n]; int li = bitsearch(n) + 1; for(int j = 1;j <= li;++j){ for(int i = 1;i <= n;++i){ if(i + p[j] > n){ if(i + p[j - 1] <= n) dp[i][j] = max(dp[i][j-1],dp[i+p[j-1]][j-1]); else dp[i][j] = dp[i][j-1]; continue; } dp[i][j] = max(dp[i][j-1],dp[i+p[j-1]][j-1]); } } int l = 1,r = n,mid,ans = -1; while(l <= r){ mid = (l + r) >> 1; if(judge(mid)){ ans = mid; r = mid - 1; } else l = mid + 1; } printf("%d\n",ans); } return 0; }