【题解】我也不是B ifrog 1112 二分 倍增

题目传送门:http://ifrog.cc/acm/problem/1112

神奇的倍增二分,长见识了,在此做个记录,分享给大家。

懒得写题解了,直接转YJQ的:http://ifrog.cc/acm/solution/18

另外,这个复杂度的证明我不是很懂,只会自己瞎脑补的不严谨的证明,如果哪位神犇会,还请教教我qwq。

代码:

 1 #include <cstring>
 2 #include <algorithm>
 3 #include <cstdio>
 4 
 5 using namespace std;
 6 typedef long long ll;
 7 const int MAXN = 300010;
 8 
 9 int n;
10 ll m, a[MAXN], v[MAXN];
11 int ans[MAXN] = {0};
12 
13 ll tmp[MAXN];
14 bool check( int begin, int end ) { // 区间混乱度大于m返回true
15     for( int i = begin; i < end; ++i ) tmp[i] = a[i];
16     sort(tmp+begin, tmp+end);
17     ll sum = 0;
18     for( int i = begin; i < end; ++i )
19         sum += tmp[i] * v[i-begin];
20     return sum > m;
21 }
22 
23 int main() {
24     scanf( "%d%lld", &n, &m );
25     for( int i = 0; i < n; ++i ) scanf( "%lld", a+i );
26     for( int i = 0; i < n; ++i ) scanf( "%lld", v+i );
27     for( int i = 0; i < n; ) {
28         int k;
29         for( k = 1; i+k <= n; k <<= 1 ) // 倍增,左闭右开区间
30             if( check(i,i+k) ) break;
31         k = min(k, n-i);
32         int low = i+(k>>1), high = i+k;
33         while( low < high ) { // 二分
34             int mid = (low+high)>>1;
35             if( check(i,mid) ) high = mid;
36             else low = mid+1;
37         }
38         if( check(i,low) ) ans[low-1] = 1;
39         i = low;
40         // printf( "low = %d\n", low );
41     }
42     for( int i = 0; i < n; ++i ) {
43         if(i) ans[i] += ans[i-1], putchar(' ');
44         printf( "%d", ans[i] );
45     }
46     puts("");
47     return 0;
48 }

 

posted @ 2017-04-01 17:25  mlystdcall  阅读(346)  评论(0编辑  收藏  举报