fork download
  1.  
  2. import java.io.*;
  3.  
  4. public class Main {
  5.  
  6. static class EntradaRapida {
  7. private final BufferedInputStream entrada =
  8.  
  9. private final byte[] datos = new byte[1 << 16];
  10. private int pos = 0;
  11. private int longitud = 0;
  12.  
  13. private int leer() throws IOException {
  14. if (pos >= longitud) {
  15. longitud = entrada.read(datos);
  16. pos = 0;
  17.  
  18. if (longitud <= 0) return -1;
  19. }
  20.  
  21. return datos[pos++] & 255;
  22. }
  23.  
  24. int leerEntero() throws IOException {
  25. int caracter;
  26.  
  27. do {
  28. caracter = leer();
  29. if (caracter == -1) return -1;
  30. } while (caracter <= 32);
  31.  
  32. int signo = 1;
  33.  
  34. if (caracter == '-') {
  35. signo = -1;
  36. caracter = leer();
  37. }
  38.  
  39. int valor = 0;
  40.  
  41. while (caracter > 32 && caracter != -1) {
  42. valor = valor * 10 + caracter - '0';
  43. caracter = leer();
  44. }
  45.  
  46. return valor * signo;
  47. }
  48.  
  49. String leerCadena() throws IOException {
  50. StringBuilder resultado = new StringBuilder();
  51. int caracter;
  52.  
  53. do {
  54. caracter = leer();
  55. if (caracter == -1) return null;
  56. } while (caracter <= 32);
  57.  
  58. while (caracter > 32 && caracter != -1) {
  59. resultado.append((char) caracter);
  60. caracter = leer();
  61. }
  62.  
  63. return resultado.toString();
  64. }
  65.  
  66. char leerLetra() throws IOException {
  67. int caracter;
  68.  
  69. do {
  70. caracter = leer();
  71. } while (caracter != -1 && caracter <= 32);
  72.  
  73. return caracter == -1 ? '\0' : (char) caracter;
  74. }
  75. }
  76.  
  77. static class ArbolSegmentos {
  78. private final int inicioArbol;
  79. private final int[] segmentos;
  80. private final int longitud;
  81.  
  82. ArbolSegmentos(char[] letras) {
  83. longitud = letras.length;
  84.  
  85. int capacidad = 1;
  86.  
  87. while (capacidad < longitud) {
  88. capacidad <<= 1;
  89. }
  90.  
  91. inicioArbol = capacidad;
  92. segmentos = new int[inicioArbol << 1];
  93.  
  94. construir(letras);
  95. }
  96.  
  97. private int mascara(char caracter) {
  98. if (caracter < 'a' || caracter > 'z') {
  99. return 0;
  100. }
  101.  
  102. return 1 << (caracter - 'a');
  103. }
  104.  
  105. private void construir(char[] letras) {
  106. for (int i = 0; i < longitud; i++) {
  107. segmentos[inicioArbol + i] = mascara(letras[i]);
  108. }
  109.  
  110. for (int i = inicioArbol - 1; i > 0; i--) {
  111. segmentos[i] =
  112. segmentos[i << 1] |
  113. segmentos[i << 1 | 1];
  114. }
  115. }
  116.  
  117. void actualizar(int indice, char nuevoCaracter) {
  118. if (indice < 0 || indice >= longitud) return;
  119.  
  120. int actual = inicioArbol + indice;
  121.  
  122. segmentos[actual] = mascara(nuevoCaracter);
  123.  
  124. actual >>= 1;
  125.  
  126. while (actual > 0) {
  127. segmentos[actual] =
  128. segmentos[actual << 1] |
  129. segmentos[actual << 1 | 1];
  130.  
  131. actual >>= 1;
  132. }
  133. }
  134.  
  135. int consultar(int inicio, int fin) {
  136. if (inicio < 0 || fin >= longitud || inicio > fin) {
  137. return 0;
  138. }
  139.  
  140. inicio += inicioArbol;
  141. fin += inicioArbol + 1;
  142.  
  143. int resultado = 0;
  144.  
  145. while (inicio < fin) {
  146. if ((inicio & 1) != 0) {
  147. resultado |= segmentos[inicio++];
  148. }
  149.  
  150. if ((fin & 1) != 0) {
  151. resultado |= segmentos[--fin];
  152. }
  153.  
  154. inicio >>= 1;
  155. fin >>= 1;
  156. }
  157.  
  158. return Integer.bitCount(resultado);
  159. }
  160. }
  161.  
  162. static void resolver(EntradaRapida entrada) throws IOException {
  163. String cadena = entrada.leerCadena();
  164.  
  165. if (cadena == null) return;
  166.  
  167. char[] caracteres = cadena.toCharArray();
  168.  
  169. int totalConsultas = entrada.leerEntero();
  170.  
  171. if (totalConsultas < 0) return;
  172.  
  173. ArbolSegmentos arbol = new ArbolSegmentos(caracteres);
  174.  
  175. StringBuilder salida = new StringBuilder();
  176.  
  177. for (int i = 0; i < totalConsultas; i++) {
  178. int operacion = entrada.leerEntero();
  179.  
  180. if (operacion == -1) break;
  181.  
  182. if (operacion == 1) {
  183. int indice = entrada.leerEntero() - 1;
  184. char nuevoCaracter = entrada.leerLetra();
  185.  
  186. if (indice >= 0 &&
  187. indice < caracteres.length &&
  188. nuevoCaracter >= 'a' &&
  189. nuevoCaracter <= 'z') {
  190.  
  191. caracteres[indice] = nuevoCaracter;
  192. arbol.actualizar(indice, nuevoCaracter);
  193. }
  194.  
  195. } else if (operacion == 2) {
  196. int inicio = entrada.leerEntero() - 1;
  197. int fin = entrada.leerEntero() - 1;
  198.  
  199. salida.append(
  200. arbol.consultar(inicio, fin)
  201. ).append('\n');
  202. }
  203. }
  204.  
  205. System.out.print(salida);
  206. }
  207.  
  208. public static void main(String[] args) throws IOException {
  209. resolver(new EntradaRapida());
  210. }
  211. }
  212.  
Success #stdin #stdout 0.06s 52704KB
stdin
Standard input is empty
stdout
Standard output is empty