NOIP模拟70
T3:
考虑首先显然可以按行分别考虑,问题为如何快速计算一段区间的贡献
考虑合并区间,然而并没有发现正确的合并策略,于是考虑优化暴力,利用倍增
发现一个显然的贪心策略为由于每个位置比选,于是从区间第一个x开始k长度贪心选择即可
发现枚举x位置的过程可以进行倍增优化,设计dp转移每个位置往后2^j个k区间即可
代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define I int 4 #define C char 5 #define B bool 6 #define V void 7 #define LL long long 8 #define UI unsigned int 9 #define UL unsigned long long 10 #define P pair<I,I> 11 #define MP make_pair 12 #define a first 13 #define b second 14 #define lowbit(x) (x & -x) 15 #define debug cout << "It's Ok Here !" << endl; 16 #define FP(x) freopen (#x,"r",stdin) 17 #define FC(x) freopen (#x,"w",stdout) 18 const I N = 1e5 + 3; 19 I H,W,K,Q,D,L,R,tmp[N],pos[15][N][20]; 20 C s[15][N]; 21 inline I read () { 22 I x(0),y(1); C z(getchar()); 23 while (!isdigit(z)) { if (z == '-') y = -1; z = getchar(); } 24 while ( isdigit(z)) x = x * 10 + (z ^ 48), z = getchar(); 25 return x * y; 26 } 27 inline V Max (I &a,I b) { a = a > b ? a : b; } 28 inline V Min (I &a,I b) { a = a < b ? a : b; } 29 inline I max (I a,I b) { return a > b ? a : b; } 30 inline I min (I a,I b) { return a < b ? a : b; } 31 inline V swap (I &a,I &b) { a ^= b, b ^= a, a ^= b; } 32 inline I abs (I a) { return a >= 0 ? a : -a; } 33 inline P operator + (const P &a,const P &b) { 34 return MP (a.a + b.a,a.b + b.b); 35 } 36 inline P operator - (const P &a,const P &b) { 37 return MP (a.a - b.a,a.b - b.b); 38 } 39 40 signed main () { 41 FP (blueshit.in), FC (blueshit.out); 42 H = read (), W = read (), K = read (), Q = read (); 43 for (I i(1);i <= W; ++ i) 44 tmp[i] = log2 (i); 45 for (I i(1);i <= H; ++ i) { 46 scanf ("%s",s[i] + 1); 47 for (I j(1);j <= W; ++ j) { 48 pos[i][j][0] = s[i][j] == 'X' ? 49 j : pos[i][j - 1][0]; 50 for (I k(1);k <= tmp[j]; ++ k) 51 pos[i][j][k] = pos[i][max (pos[i][j][k - 1] - K,0)][k - 1]; 52 } 53 } 54 while (Q -- ) { 55 I ans (0); 56 D = read (), L = read (), R = read (); 57 for (I i(1);i <= D; ++ i) { 58 I it (R), len (R - L + 1); 59 for (I j(tmp[len]); ~j ; -- j) 60 if (pos[i][it][j] >= L) 61 ans += 1 << j, it = max (pos[i][it][j] - K,0); 62 } 63 printf ("%d\n",ans); 64 } 65 }