数字串
题解:有点像找逆序对,因为子串的长度有限制,所以对于每一个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 }