zoukankan      html  css  js  c++  java
  • Dynamic Rankings

    传送门

    这道题是带修主席树的板子题。我们先来考虑一下主席树带修改最暴力的做法,就是暴力修改与之有关的所有权值线段树,这样的话单次操作的复杂度就是(O(nlogn))的,总体的操作就是(O(n^2logn))的,显然吃不消。

    因为主席树其实应用的是前缀和的思想,我们考虑一下在最开始的时候,我们是怎么维护单点修改的前缀和的?使用树状数组。在普通的主席树里我们用的是差分的思想,但是现在我们不用差分了,我们用树状数组的思想(有人说叫套一个树状数组,但是其实我觉得没有实际套上……怎么说都行),使得根节点为(root_x)的主席树维护的是(lowbit_x)区间之内的权值,修改的时候像树状数组一样修改,查询的时候也一样查询,之后就和普通的主席树很相似了。

    在实现上还是有很多细节的。修改和建树不难,因为这时不需要考虑继承上一个根结点的信息,直接修改就可以。不过在查询的时候,我们不能先进入树中之后再调用(lowbit)进行循环查询,因为进入树中之后我们就不知道下一步往哪走了。所以解决办法是一开始先把(l-1)(r)能访问到的区间都跑出来,把他们的根节点存在数组里,之后在询问的时候,同步的把所有根节点都向其左/右儿子移动就可以了,顺便使用这个来统计答案,确定应该往哪边走。

    这样的话这道题修改是(O(log^2n)),总复杂度为(O(nlog^2n)),可以通过。

    还有就是此题实际上不需要离散化,因为主席树上权值只是用来帮你判断应该往哪走,这题因为没要求强制在线,所以可以像我一样,先离线把所有的都存下来,之后进行离散化之后再操作,也可以不离散直接操作,但是这样二分的边界会大一点。

    我自己试了一下,对于普通的主席树,其实离不离散对于答案的正确性影响不大,但是如果不离散,那么二分的范围必须开到上下界,也就是稳定的(O(nlogmax_{val})),但是离散化以后就会好很多。不离散的话会浪费时间和空间,不过其实也不会太多,一般会多几个常数的(O(n))复杂度,差的不是很多。比如这题离不离散只差了1000ms(一共14000ms)。

    所以离不离散的话可能ssy说的对:“你觉得不离散过不去的时候。”

    看一下代码。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    #define pr pair<int,int>
    #define mp make_pair
    #define fi first
    #define sc second
    #define lowbit(x) x & (-x)
    using namespace std;
    typedef long long ll;
    const int M = 400005;
    const int N = 30000005;
     
    int read()
    {
       int ans = 0,op = 1;
       char ch = getchar();
       while(ch < '0' || ch > '9')
       {
          if(ch == '-') op = -1;
          ch = getchar();
       }
       while(ch >='0' && ch <= '9')
       {
          ans *= 10;
          ans += ch - '0';
          ch = getchar();
       }
       return ans * op;
    }
    
    struct node
    {
       int ls,rs,v;
    }t[N];
    
    int a[M],b[M],n,m,x[M],y[M],z[M],c[M],idx,t1[M],t2[M],cnt1,cnt2,root[M],tot;
    char s[2];
    
    void modify(int &p,int l,int r,int pos,int val)
    {
       if(!p) p = ++idx;
       t[p].v += val;
       if(l == r) return;
       int mid = (l+r) >> 1;
       if(pos <= mid) modify(t[p].ls,l,mid,pos,val);
       else modify(t[p].rs,mid+1,r,pos,val);
    }
    
    void change(int pos,int val)
    {
       int x = pos;
       while(x <= n) modify(root[x],1,tot,a[pos],-1),x += lowbit(x);
       a[pos] = val,x = pos;
       while(x <= n) modify(root[x],1,tot,a[pos],1),x += lowbit(x);
    }
    
    int query(int l,int r,int k)
    {
       if(l == r) return l;
       int sum = 0,mid = (l+r) >> 1;
       rep(i,1,cnt1) sum -= t[t[t1[i]].ls].v;
       rep(i,1,cnt2) sum += t[t[t2[i]].ls].v;
       if(k <= sum)
       {
          rep(i,1,cnt1) t1[i] = t[t1[i]].ls;
          rep(i,1,cnt2) t2[i] = t[t2[i]].ls;
          return query(l,mid,k);
       }
       else
       {
          rep(i,1,cnt1) t1[i] = t[t1[i]].rs;
          rep(i,1,cnt2) t2[i] = t[t2[i]].rs;
          return query(mid+1,r,k - sum);
       }
    }
    
    int main()
    {
       n = read(),m = read();
       rep(i,1,n) a[i] = b[i] = read();
       rep(i,1,m)
       {
          scanf("%s",s);
          if(s[0] == 'Q') x[i] = read(),y[i] = read(),z[i] = read();
          else c[i] = read(),a[i+n] = b[i+n] = read();
       }
       sort(b+1,b+n+m+1);
       tot = unique(b+1,b+1+n+m) - b - 1;
       rep(i,1,n+m) a[i] = lower_bound(b+1,b+1+tot,a[i]) - b;
       rep(i,1,n)
       {
          int j = i;
          while(j <= n) modify(root[j],1,tot,a[i],1),j += lowbit(j);
       }
       rep(i,1,m)
       {
          if(!x[i]) {change(c[i],a[i+n]);continue;}
          int j = x[i] - 1,k = y[i];
          cnt1 = cnt2 = 0;
          while(j) t1[++cnt1] = root[j],j -= lowbit(j);
          while(k) t2[++cnt2] = root[k],k -= lowbit(k);
          printf("%d
    ",b[query(1,tot,z[i])]);
       }
       return 0;
    }
    
    
  • 相关阅读:
    【刷题】LOJ 6038 「雅礼集训 2017 Day5」远行
    【刷题】BZOJ 4650 [Noi2016]优秀的拆分
    【刷题】BZOJ 4566 [Haoi2016]找相同字符
    【刷题】BZOJ 3238 [Ahoi2013]差异
    微信公众号_订阅号_被动回复用户消息
    艺术模板 art-template-web
    AJAX_违反了同源策略_就是"跨域"——jsonp 和 cors
    Ajax_简介: 异步的 JS 和 XML_原生写 ajax 分析其原理_jquery_ajax_art-template
    Node.js_express_临时会话对象 session
    BOM 浏览器对象模型_XMLHttpRequest 对象
  • 原文地址:https://www.cnblogs.com/captain1/p/10099826.html
Copyright © 2011-2022 走看看