zoukankan      html  css  js  c++  java
  • HDU 5919 Sequence II

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5919

    ------------------------------------------------------------------------------------

    现场赛的时候由于不会主席树就用分块卡过去了

    现在学习了主席树后感觉这题也是很有意思的

    首先 这题要把问题转化为对于一段区间 求一个左端点相同的$($如果有多个取右端点最靠左的$)$子区间

    这个子区间的不同数的个数等于原区间不同数的个数除二向上取整

    求区间不同数个数是主席树模板题之一 建议先做完下面这题再来看

    http://www.cnblogs.com/sagitta/p/5937253.html

    对于这题 由于不是求一个给定区间不同数的个数 看起来似乎还需要对子区间右端点进行二分才行

    如果真的按照这种思路就是$O(NlogN + Qlog^{2}N)$了 虽然此题也不卡这种解法

    但是考虑到有不少线段树$/ST$表$/$倍增 再加一个二分的题目实际操作中并不需要在外层套一个二分

    因此这里我们也可以试着看看能否直接利用线段树维护的区间上的信息来免去二分

    再对问题进行观察 我们发现要求的子区间与原区间的左端点是一样的 即子区间左端点是固定的

    因此我们可以考虑在主席树上维护后缀区间而不是前缀区间

    维护后缀区间的话 我们只需在主席树上每次对左右区间进行判断到底往那个区间走就行$($逐步确定右端点位置$)$

    这样就是$O(NlogN + QlogN)$的了

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 const int N = 2e5 + 10, T = N * 40;
      4 int sum[T], ch[T][2], root[N << 1], ma[N], last[N];
      5 int a[N];
      6 int croot, cnt, n, q;
      7 int build(int x, int L, int R)
      8 {
      9     if(L == R)
     10     {
     11         sum[x] = 0;
     12         return x;
     13     }
     14     int mid = (L + R) >> 1;
     15     ch[x][0] = build(++cnt, L, mid);
     16     ch[x][1] = build(++cnt, mid + 1, R);
     17     sum[x] = sum[ch[x][0]] + sum[ch[x][1]];
     18     return x;
     19 }
     20 int update(int x, int L, int R, int y, int delta, int pre)
     21 {
     22     if(L == R)
     23     {
     24         sum[x] = sum[pre] + delta;
     25         return x;
     26     }
     27     int mid = (L + R) >> 1;
     28     if(y <= mid)
     29     {
     30         ch[x][0] = update(++cnt, L, mid, y, delta, ch[pre][0]);
     31         ch[x][1] = ch[pre][1];
     32     }
     33     else
     34     {
     35         ch[x][0] = ch[pre][0];
     36         ch[x][1] = update(++cnt, mid + 1, R, y, delta, ch[pre][1]);
     37     }
     38     sum[x] = sum[ch[x][0]] + sum[ch[x][1]];
     39     return x;
     40 }
     41 int query(int x, int L, int R, int r)
     42 {
     43     if(R <= r)
     44         return sum[x];
     45     int mid = (L + R) >> 1;
     46     if(r <= mid)
     47         return query(ch[x][0], L, mid, r);
     48     return sum[ch[x][0]] + query(ch[x][1], mid + 1, R, r);
     49 }
     50 int findkth(int x, int L, int R, int k)
     51 {
     52     if(L == R)
     53         return L;
     54     int mid = (L + R) >> 1;
     55     if(k <= sum[ch[x][0]])
     56         return findkth(ch[x][0], L, mid, k);
     57     else
     58         return findkth(ch[x][1], mid + 1, R, k - sum[ch[x][0]]);
     59 }
     60 int t;
     61 int main()
     62 {
     63     scanf("%d", &t);
     64     for(int ca = 1; ca <= t; ++ca)
     65     {
     66         croot = cnt = 0;
     67         memset(last, 0, sizeof last);
     68         scanf("%d%d", &n, &q);
     69         root[++croot] = ++cnt;
     70         ma[0] = 1;
     71         build(cnt, 1, n);
     72         for(int i = 1; i <= n; ++i)
     73             scanf("%d", &a[i]);
     74         for(int i = n; i; --i)
     75         {
     76             ++croot;
     77             root[croot] = update(++cnt, 1, n, i, 1, root[croot - 1]);
     78             if(last[a[i]])
     79             {
     80                 ++croot;
     81                 root[croot] = update(++cnt, 1, n, last[a[i]], -1, root[croot - 1]);
     82             }
     83             last[a[i]] = i;
     84             ma[i] = root[croot];
     85         }
     86         printf("Case #%d:", ca);
     87         int ans = 0, l, r, x, y;
     88         while(q--)
     89         {
     90             scanf("%d%d", &x, &y);
     91             l = min((x + ans) % n + 1, (y + ans) % n + 1);
     92             r = max((x + ans) % n + 1, (y + ans) % n + 1);
     93             int cnt = query(ma[l], 1, n, r);
     94             ans = findkth(ma[l], 1, n, (cnt + 1) / 2);
     95             printf(" %d", ans);
     96         }
     97         puts("");
     98     }
     99     return 0;
    100 }
  • 相关阅读:
    微信小程序开发前期准备
    怎样在vs2013和vs2015中实现自动编译sass
    在MVC中使用Bundle打包压缩js和css
    Html5 突破微信限制实现大文件分割上传
    Automapper 实现自动映射
    Polly一种.NET弹性和瞬态故障处理库(重试策略、断路器、超时、隔板隔离、缓存、回退、策略包装)
    关于transactionscope 事务的脏数据
    IIS设置session时长
    已禁用对分布式事务管理器(MSDTC)的网络访问的解决方法之一
    DAL.SQLHelper 的类型初始值设定项引发异常的处理
  • 原文地址:https://www.cnblogs.com/sagitta/p/5938742.html
Copyright © 2011-2022 走看看