tcbpg

UVA 11235 - Frequent Values

Mar 13th, 2012
252
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.82 KB | None | 0 0
  1. /*
  2. PROBLEMA: UVa 11235 - Frequent Values
  3.  
  4. Salio usando Range Maximum Query con Segment Tree. La idea es la siguiente:
  5.  
  6. Hacemos un array count[i] que cuenta cuantos elementos hay iguales al i-esimo elemento sin considerar repetidos.
  7. Despues hacemos el acumulado (inclusive) ac[i] = suma(count[i..j]).
  8.  
  9. Hacemos el segment tree del arreglo count.
  10.  
  11. Supongamos que nos hacen la query i,j
  12.  
  13. Con busqueda binaria obtenemos l y r tales que ac[l] <= i y ac[r] <= j. Si l == r entonces es fácil porque a[i] = a[j] y entonces es la cantidad de elementos que hay en el medio. Sino, lo que hacemos es usar el set de segment tree para corregir los valores de count[l] y de count[r] a la cantidad de elementos entre ac[l] e i y entre ac[r] y j. Eso lo puedo hacer en O(log n) por la magia de segment tree. Despues es hacer el range maximum query común y silvestre.
  14.  
  15. O sea que nos queda O(n + q log n)
  16.  
  17. */
  18.  
  19. #include <iostream>
  20. #include <cstdio>
  21. #include <climits>
  22. #include <cstring>
  23. using namespace std;
  24. typedef pair<int,int> pii;
  25. #define forn(i,n) for(int i=0;i<(int)(n);i++)
  26. #define forsn(i,s,n) for(int i=(int)(s);i<(int)(n);i++)
  27.  
  28. const int MAXN=100100;
  29. int n,q,a[MAXN];
  30. int S,count[MAXN],ac[MAXN];
  31. int rmq[4*MAXN], R;
  32.  
  33. //Segment Tree
  34. void initTree(){
  35.     R = 1 << (32-__builtin_clz(S));
  36.     forsn(i,R,2*R) rmq[i] = 0;
  37.     forn(i,R) rmq[R+i] = count[i];
  38.     for(int i = R-1; i >= 0; i--)
  39.         rmq[i] = max(rmq[2*i],rmq[2*i+1]);
  40. }
  41. void set(int i, int v){
  42.     rmq[i+=R] = v;
  43.     for(int p = i/2; p != 0; p = p/2){
  44.         rmq[p] = max(rmq[2*p],rmq[2*p+1]);
  45.     }
  46. }
  47. int _get(int i, int j){
  48.     int res = 0;
  49.     if(j-i <= 0) return res;
  50.     if(i % 2) res = max(res,rmq[i++]);
  51.     res = max(res, _get(i/2,j/2));
  52.     if(j % 2) res = max(res,rmq[--j]);
  53.     return res;
  54. }
  55. int get(int i, int j){ return _get(i+R, j+R); }
  56. //Fin Segment Tree
  57.  
  58. void init(){
  59.     int b = INT_MIN; S = 0;
  60.     forn(i,n){
  61.         if(a[i] == b){
  62.             count[S-1]++;
  63.         }else{
  64.             b = a[i]; count[S++] = 1;
  65.         }
  66.     }
  67.     ac[0] = count[0];
  68.     forn(i,S) ac[i] = ac[i-1] + count[i-1];
  69.  
  70.     initTree();
  71. }
  72. int bsearch(int v){
  73.     int l = 0, r = S;
  74.     while(r-l>1){
  75.         int m = (r+l)/2;
  76.         if(ac[m] <= v) l = m; else r = m;
  77.     }
  78.     return l;
  79. }
  80. int query(int left, int right){
  81.     int l = bsearch(left), r = bsearch(right);
  82.     if(l == r) return right-left;
  83.     int oril = -1, orir = -1;
  84.     if(left - ac[l] > 0){
  85.         oril = count[l];
  86.         set(l,count[l]-left+ac[l]);
  87.     }
  88.     if(ac[r] + count[r] - right > 0){
  89.         orir = count[r];
  90.         set(r,right-ac[r]);
  91.     }
  92.  
  93.     int res = get(l,r+1);
  94.  
  95.     if(oril >= 0) set(l,oril);
  96.     if(orir >= 0) set(r,orir);
  97.     return res;
  98. }
  99. int main(){
  100.     #ifdef JUAMPI
  101.         freopen("11235.in","r",stdin);
  102.     #endif
  103.    
  104.     while(scanf("%d",&n) == 1 && n > 0){
  105.         scanf("%d",&q);
  106.        
  107.         forn(i,n) scanf("%d",&a[i]);
  108.         init();
  109.        
  110.         forn(i,q){
  111.             int l,r; scanf("%d %d",&l,&r);
  112.             l--;
  113.             printf("%d\n",query(l,r));
  114.         }
  115.     }
  116.    
  117.     return 0;
  118. }
Advertisement
Add Comment
Please, Sign In to add comment