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 }
View Code

 

posted @ 2021-10-06 21:42  HZOI_LYM  阅读(70)  评论(0编辑  收藏  举报