• 带修改主席树 (树状数组+主席树)


    终于学了这个我仰慕已久的算法。

    对于待修改的主席树我们只需要多开一维,进行修改后的求和。复杂度进化为O(nlog^2n)

    我们需要开R0 L0两个数组记录树状数组的“路径”

    然后其他操作就和主席树一样咯!

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int N=60006;
      4 vector<int>v;
      5 int n,m,cnt,mx;
      6 int R0[N],L0[N],a[N],R[N],rt[N];
      7 struct node
      8 {
      9     int l,r,s;
     10 }t[N*40];
     11 struct que
     12 {
     13     int f,l,r,x,p,k;
     14 }q[N/6];
     15 inline int get(int x){return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}
     16 void build(int &x,int l,int r)
     17 {
     18     int m=(l+r)>>1;x=++cnt;
     19     if(l<r)
     20     build(t[x].l,l,m),build(t[x].r,m+1,r);
     21 }
     22 inline int lowbit(int x){return x&(-x);}
     23 int update(int l,int r,int p,int root,int w)
     24 {
     25     int x=++cnt;int m=(l+r)>>1;
     26     t[x].s=t[root].s+w;
     27     if(l==r)return x;
     28     if(p<=m)
     29     {
     30         t[x].l=update(l,m,p,t[root].l,w);
     31         t[x].r=t[root].r;
     32     }
     33     else
     34     {
     35         t[x].r=update(m+1,r,p,t[root].r,w);
     36         t[x].l=t[root].l;
     37     }
     38     return x;
     39 }
     40 void add(int pos,int x,int w)
     41 {
     42     for(;pos<=n;pos+=lowbit(pos))R[pos]=update(1,mx,x,R[pos],w);
     43 }
     44 int query(int l,int r,int k,int lrt,int rrt)
     45 {
     46     if(l==r)return l;
     47     int ls=0,rs=0,m=(l+r)>>1;
     48     int sum=t[t[rrt].l].s-t[t[lrt].l].s;
     49     for(int i=1;i<=R0[0];++i)rs+=t[t[R0[i]].l].s;
     50     for(int i=1;i<=L0[0];++i)ls+=t[t[L0[i]].l].s;
     51     if(k<=rs-ls+sum)
     52     {
     53         for(int i=1;i<=R0[0];++i)R0[i]=t[R0[i]].l;
     54         for(int i=1;i<=L0[0];++i)L0[i]=t[L0[i]].l;
     55         return query(l,m,k,t[lrt].l,t[rrt].l);
     56     }
     57     else
     58     {
     59         for(int i=1;i<=R0[0];++i)R0[i]=t[R0[i]].r;
     60         for(int i=1;i<=L0[0];++i)L0[i]=t[L0[i]].r;
     61         return query(m+1,r,k-rs+ls-sum,t[lrt].r,t[rrt].r);
     62     }
     63 }
     64 void cal(int l,int r,int k)
     65 {
     66     R0[0]=L0[0]=0;
     67     for(int x=r;x;x-=lowbit(x))
     68     {
     69         R0[++R0[0]]=R[x];
     70     }
     71     for(int x=l;x;x-=lowbit(x))
     72     {
     73         L0[++L0[0]]=R[x];
     74     }
     75     printf("%d
    ",v[query(1,mx,k,rt[l],rt[r])-1]);
     76 }
     77 char s[3];
     78 int main()
     79 {
     80     scanf("%d%d",&n,&m);
     81     for(int i=1;i<=n;++i)
     82     {
     83         scanf("%d",&a[i]);v.push_back(a[i]);
     84     }mx=n+m;
     85     for(int i=1;i<=m;++i)
     86     {
     87         scanf("%s",s);
     88         if(s[0]=='Q')
     89         {
     90             scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k);q[i].f=0;
     91         }
     92         else
     93         {
     94             scanf("%d%d",&q[i].p,&q[i].x);q[i].f=1;v.push_back(q[i].x);
     95         }
     96     }
     97     sort(v.begin(),v.end());
     98     v.erase(unique(v.begin(),v.end()),v.end());mx=v.size();
     99     build(rt[0],1,mx);
    100     for(int i=1;i<=n;++i)rt[i]=update(1,mx,get(a[i]),rt[i-1],1);
    101     for(int i=1;i<=m;++i)
    102     {
    103         if(!q[i].f)cal(q[i].l-1,q[i].r,q[i].k);
    104         else
    105         {
    106             add(q[i].p,get(a[q[i].p]),-1);add(q[i].p,get(q[i].x),1);
    107             a[q[i].p]=q[i].x; 
    108         }
    109     }
    110     return 0;
    111 }
  • 相关阅读:
    背包问题
    阶乘尾数0的个数
    欧拉筛找素数
    威佐夫博弈
    三角形面积
    deleted
    deleted
    deleted
    deleted
    deleted
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8007203.html
Copyright © 2020-2023  润新知