待修改主席树 (树状数组+主席树)

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

对于待修改的主席树我们只需要多开一维,进行修改后的求和。复杂度进化为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\n",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 }
时间: 2024-10-18 14:27:25

待修改主席树 (树状数组+主席树)的相关文章

【bzoj1146】[CTSC2008]网络管理Network 倍增LCA+dfs序+树状数组+主席树

题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高速光缆组成.每个部门都有一个专属的路由器,部门局域网内的所有机器都联向这个路由器,然后再通过这个通信子网与其他部门进行通信联络.该网络结构保证网络中的任意两个路由器之间都存在一条直接或间接路径以进行通信. 高速光缆的数据传输速度非常快,以至于利用光缆传输的延迟时间可以忽略.但是由于路由器老化,在这些

【BZOJ】1146: [CTSC2008]网络管理Network(树链剖分+线段树套平衡树+二分 / dfs序+树状数组+主席树)

第一种做法(时间太感人): 这题我真的逗了,调了一下午,疯狂造数据,始终找不到错. 后来发现自己sb了,更新那里没有打id,直接套上u了.我.... 调了一下午啊!一下午的时光啊!本来说好中午A掉去学习第二种做法,噗 好吧,现在第一种做法是hld+seg+bst+二分,常数巨大,log^4级别,目前只会这种. 树剖后仍然用线段树维护dfs序区间,然后在每个区间建一颗平衡树,我用treap,(这题找最大啊,,,囧,并且要注意,这里的rank是比他大的数量,so,我们在二分时判断要判断一个范围,即要

【bzoj3744】Gty的妹子序列 分块+树状数组+主席树

题目描述 我早已习惯你不在身边, 人间四月天 寂寞断了弦. 回望身后蓝天, 跟再见说再见…… 某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现 她们排成了一个序列,每个妹子有一个美丽度. Bakser神犇与他打算研究一下这个妹子序列,于是Bakser神犇问道:"你知道区间 [l,r]中妹子们美丽度的逆序对数吗?" 蒟蒻Autumn只会离线乱搞啊……但是Bakser神犇说道:"强制在线." 请你帮助一下Autumn吧.

【BZOJ】1047: [HAOI2007]理想的正方形(单调队列/~二维rmq+树状数组套树状数组)

http://www.lydsy.com/JudgeOnline/problem.php?id=1047 树状数组套树状数组真心没用QAQ....首先它不能修改..而不修改的可以用单调队列做掉,而且更快,只有O(n^2).而这货是n^2log^2n的建树...虽然查询是log^2n...但是建树那里就tle了.. 那么说题解... 先orz下,好神.. 我怎么没想到单调队列orz 首先我们维护 行 的单调队列,更新每个点在 列 距离内的最小and最大的值 然后我们维护 列 的单调队列,更新每个点

hdu 1166 树状数组 线段树

敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 51177    Accepted Submission(s): 21427 Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务

hdu1394(枚举/树状数组/线段树单点更新&amp;区间求和)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 题意:给出一个循环数组,求其逆序对最少为多少: 思路:对于逆序对: 交换两个相邻数,逆序数 +1 或 -1, 交换两个不相邻数 a, b, 逆序数 += 两者间大于 a 的个数 - 两者间小于 a 的个数: 所以只要求出初始时的逆序对数,就可以推出其余情况时的逆序对数.对于求初始逆序对数,这里 n 只有 5e3,可以直接暴力 / 树状数组 / 线段树 / 归并排序: 代码: 1.直接暴力 1

【BZOJ-1452】Count 树状数组 套 树状数组

1452: [JSOI2009]Count Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1769  Solved: 1059[Submit][Status][Discuss] Description Input Output Sample Input Sample Output 1 2 HINT Source Solution 忽略标题的说法...撞壁用的.... 简单题,裸树状数组套树状数组 颜色数目$c<=100$很小,考虑对于每种颜色单独进

HDU 1394 Minimum Inversion Number 树状数组&amp;&amp;线段树

题目给了你一串序列,然后每次 把最后一个数提到最前面来,直到原来的第一个数到了最后一个,每次操作都会产生一个新的序列,这个序列具有一个逆序数的值,问最小的你逆序数的值为多少 逆序数么 最好想到的是树状数组,敲了一把很快,注意把握把最后一个数提上来对逆序数的影响即可, #include<iostream> #include<cstdio> #include<list> #include<algorithm> #include<cstring> #i

HDU 1166 敌兵布阵 (树状数组&#183;线段树)

题意  中文 动态区间和问题   只会更新点  最基础的树状数组 线段树的应用 树状数组代码 #include <bits/stdc++.h> using namespace std; const int N = 50005; int c[N], n, m; void add(int p, int x) { while(p <= n) c[p] += x, p += p & -p; } int getSum(int p) { int ret = 0; while(p > 0