数字串

题解:有点像找逆序对,因为子串的长度有限制,所以对于每一个s[i],当它作为尾部时,头部的范围是(i-R+1,i-L+1);当它作为头部时,尾部的范围是(i+L-1,i+R-1)。修改的时候先减掉该位置原来的数的贡献。

 1 #pragma warning(disable:4996)
 2 #include<string>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<iostream>
 6 #include<algorithm>
 7 #define ll long long
 8 using namespace std;
 9 
10 const int maxn = 100005;
11 
12 int n, q, L, R, co[10][maxn];
13 char s[maxn];
14 
15 int lowbit(int x) {
16     return x & -x;
17 }
18 
19 void add(int o, int pos, int x) {
20     for (int i = pos; i <= n; i += lowbit(i)) co[o][i] += x;
21     return;
22 }
23 
24 int sum(int o, int pos) {
25     int res = 0;
26     for (int i = pos; i >= 1; i -= lowbit(i)) res += co[o][i];
27     return res;
28 }
29 
30 int main()
31 {
32     while (scanf("%s", s + 1) != EOF) {
33         n = strlen(s + 1);
34         scanf("%d%d%d", &q, &L, &R);
35 
36         ll ans = 0;
37         for (int i = 1; i <= n; i++) {
38             int o = s[i] - '0';
39             add(o, i, 1);
40             for (int j = o + 1; j <= 9; j++) {
41                 ans += sum(j, i - L + 1) - sum(j, i - R);
42             }
43         }
44     
45         for (int i = 1; i <= q; i++) {
46             int pos, x;
47             scanf("%d%d", &pos, &x);
48     
49             int o = s[pos] - '0';
50 
51             for (int j = o + 1; j <= 9; j++) ans -= sum(j, pos - L + 1) - sum(j, pos - R);
52             for (int j = o - 1; j >= 0; j--) ans -= sum(j, min(n, pos + R - 1)) - sum(j, min(n, pos + L - 2));
53             add(o, pos, -1);
54             add(x, pos, 1);
55             for (int j = x + 1; j <= 9; j++) ans += sum(j, pos - L + 1) - sum(j, pos - R);
56             for (int j = x - 1; j >= 0; j--) ans += sum(j, min(n, pos + R - 1)) - sum(j, min(n, pos + L - 2));
57 
58             s[pos] = '0' + x;
59 
60             printf("%lld\n", ans);
61         }
62     }
63     return 0;
64 }

 

posted @ 2018-05-13 13:40  天之道,利而不害  阅读(420)  评论(0编辑  收藏  举报