【树状数组套权值线段树】bzoj1901 Zju2112 Dynamic Rankings

谁再管这玩意叫树状数组套主席树我跟谁急

明明就是树状数组的每个结点维护一棵动态开结点的权值线段树而已

好吧,其实只有一个指针,指向该结点的权值线段树的当前结点

每次查询之前,要让指针指向根结点

不同结点的权值线段树之间毫无关联

可以看这个:http://blog.csdn.net/popoqqq/article/details/40108669?utm_source=tuicool

#include<cstdio>
#include<algorithm>
using namespace std;
struct Data
{
	int p,v;
}t[20010];
int e,en=1;
bool cmp(const Data &a,const Data &b)
{
	return a.v<b.v;
}
int n,m,a[20010],ma[20010],x[10010],y[10010],z[10010];
char op[10010][2];
struct Node{int v,ch[2];}T[20010*195];
int root[10010],now[2][10010];
void Init_root(int ql,int qr)
{
	--ql;
	for(;ql;ql-=(ql&(-ql))) now[0][ql]=root[ql];
	for(;qr;qr-=(qr&(-qr))) now[1][qr]=root[qr];
}
int qBIT(int K,int ql,int qr)
{
	int res=0;
	for(int x=ql-1;x;x-=(x&(-x))) res-=T[T[now[0][x]].ch[0]].v;
	for(int x=qr;x;x-=(x&(-x))) res+=T[T[now[1][x]].ch[0]].v;
	bool f=(res<K);
	for(int x=ql-1;x;x-=(x&(-x))) now[0][x]=T[now[0][x]].ch[f];
	for(;qr;qr-=(qr&(-qr))) now[1][qr]=T[now[1][qr]].ch[f];
	return res;
}
int Kth(int K,int ql,int qr,int l,int r)//K小值
{
    if(l==r) return l;
    int m=(l+r>>1),tmp;
    if((tmp=qBIT(K,ql,qr))>=K) return Kth(K,ql,qr,l,m);
    return Kth(K-tmp,ql,qr,m+1,r);
}
void Update(int p,int v,int cur,int l,int r)
{
	if(l==r)
	  {
	  	T[cur].v+=v;
	  	return;
	  }
	int m=(l+r>>1);
	if(p<=m)
	  {
	  	if(!T[cur].ch[0]) T[cur].ch[0]=++e;
	  	Update(p,v,T[cur].ch[0],l,m);
	  }
	else
	  {
	  	if(!T[cur].ch[1]) T[cur].ch[1]=++e;
	  	Update(p,v,T[cur].ch[1],m+1,r);
	  }
	T[cur].v=T[T[cur].ch[0]].v+T[T[cur].ch[1]].v;
}
void Update(int pp,int p,int v)
{
	for(;pp<=n;pp+=(pp&(-pp)))
	  Update(p,v,root[pp],1,en);
}
int main()
{
//	freopen("bzoj1901.in","r",stdin);
//	freopen("bzoj1901.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
	  scanf("%d",&t[i].v);
	e=n;
	for(int i=1;i<=m;++i)
	  {
	  	scanf("%s%d",op[i],&x[i]);
	  	if(op[i][0]==‘C‘)
	  	  scanf("%d",&t[++e].v);
	  	else
	  	  scanf("%d%d",&y[i],&z[i]);
	  }
	for(int i=1;i<=e;++i)
	  t[i].p=i;
	sort(t+1,t+e+1,cmp);
	ma[a[t[1].p]=1]=t[1].v;
	for(int i=2;i<=e;++i)
	  {
	  	if(t[i].v!=t[i-1].v)
	  	  ++en;
	  	ma[a[t[i].p]=en]=t[i].v;
	  }
	e=n;
	for(int i=1;i<=m;++i)
	  if(op[i][0]==‘C‘)
	    z[i]=a[++e];
	e=n;
	for(int i=1;i<=n;++i)
	  root[i]=i;
	for(int i=1;i<=n;++i)
	  Update(i,a[i],1);
	for(int i=1;i<=m;++i)
	  if(op[i][0]==‘C‘)
	    {
	      Update(x[i],a[x[i]],-1);
	      a[x[i]]=z[i];
	      Update(x[i],z[i],1);
	    }
	  else
	    {
	      Init_root(x[i],y[i]);
	      printf("%d\n",ma[Kth(z[i],x[i],y[i],1,en)]);
	    }
	return 0;
}
时间: 2024-10-10 05:08:48

【树状数组套权值线段树】bzoj1901 Zju2112 Dynamic Rankings的相关文章

【分块】【权值分块】bzoj1901 Zju2112 Dynamic Rankings

论某O(n*sqrt(n))的带修改区间k大值算法. 首先对序列分块,分成sqrt(n)块. 然后对权值分块,共维护sqrt(n)个权值分块,对于权值分块T[i],存储了序列分块的前i块的权值情况. 对于区间询问,需要获得区间中每个值出现的次数,然后按权值扫O(sqrt(n)),完整的部分我们可以通过权值分块差分(O(1))得到(比如Lb~Rb块就是T[Rb]-T[Lb-1]),零散的部分我们再维护一个额外的权值分块,累计上该值即可.O(sqrt(n)). 对于修改,直接在该位置之后的所有权值分

【bzoj3065】带插入区间K小值 替罪羊树套权值线段树

题目描述 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一下,查询区间k小值.他每次向它的随从伏特提出这样的问题: 从左往右第x个到第y个跳蚤中,a[i]第k小的值是多少.这可难不倒伏特,他在脑袋里使用函数式线段树前缀和的方法水掉了跳蚤国王的询问.这时伏特发现有些跳蚤跳久了弹跳力会有变化,有的会增大,有的会减少.这可难不倒伏特,他在脑袋里使用树状数组套线段树的方法水掉了跳蚤国王的询问.(orz 主席

POJ2352 Stars 【树状数组】or【线段树】

Stars Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 31172   Accepted: 13595 Description Astronomers often examine star maps where stars are represented by points on a plane and each star has Cartesian coordinates. Let the level of a st

天天爱跑步:桶(就是数组)/权值线段树(没打)

提取:等式转换,桶,倍增lca 对于(x,y)的一次提问,我们规定lca为(x,y)的lca d为深度,w为点出现观察员的时间 那么对于(x,lca)这段路径上的点i,此次提问能作出贡献的等式是 d[x]-d[i]=w[i] ->d[x]=w[i]+d[i] 对于(lca,y)这段路径上的点i,此次提问能作出贡献的等式是 d[x]-d[lca]+d[i]-d[lca]=w[i] ->d[x]-2*d[lca]=w[i]-d[i] 那么我们可以将提答转化为区间修改了! 在(x,lca)上将“d[

[BZOJ4785][ZJOI2017]树状数组(概率+二维线段树)

4785: [Zjoi2017]树状数组 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 297  Solved: 195[Submit][Status][Discuss] Description 漆黑的晚上,九条可怜躺在床上辗转反侧.难以入眠的她想起了若干年前她的一次悲惨的OI 比赛经历.那是一道 基础的树状数组题.给出一个长度为 n 的数组 A,初始值都为 0,接下来进行 m 次操作,操作有两种: 1 x,表示将 Ax 变成 (Ax + 1)

LightOJ 1085(树状数组+离散化+DP,线段树)

All Possible Increasing Subsequences Time Limit:3000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Appoint description: Description An increasing subsequence from a sequence A1, A2 ... An is defined by Ai1, Ai2 ... Aik, where the followi

BZOJ3295 动态逆序对 树套树, 树状数组套线段树(主席树)

Orz黄学长,蒟蒻在黄学长的带领下,通过阅读黄学长的代码!终于会了这道题! 首先我想先说一下这道题的思路(准确来说是黄学长的). 很明显,树状数组应该不用讲吧!关键是内存怎么开,维护一些什么样的数据? 其实我们通过观察,很快可以发现,你维护被删的数比维护所有的数轻松多了(不管是空间上,还是时间上).所以我们就可以从这方面想!(其实我一开始的思路,因为这道题我已经看过很久了,一直想写,毕竟是白书里面的一道例题嘛!一开始,蒟蒻的我是打算这样的用树状数组套权值线段树,并且是维护所有的数,我发现空间不够

【bzoj4605】崂山白花蛇草水 权值线段树套KD-tree

题目描述 神犇Aleph在SDOI Round2前立了一个flag:如果进了省队,就现场直播喝崂山白花蛇草水.凭借着神犇Aleph的实力,他轻松地进了山东省省队,现在便是他履行诺言的时候了.蒟蒻Bob特地为他准备了999,999,999,999,999,999瓶崂山白花蛇草水,想要灌神犇Aleph.神犇Aleph求(跪着的)蒟蒻Bob不要灌他,由于神犇Aleph是神犇,蒟蒻Bob最终答应了他的请求,但蒟蒻Bob决定将计就计,也让神犇Aleph回答一些问题.具体说来,蒟蒻Bob会在一个宽敞的广场上

20190616 权值线段树

线段树咕咕咕 我来写一个好写的权值线段树的解析吧 权值线段树是什么 线段树每个点维护的是点的值,而权值线段树叶子点维护的是一个数出现的次数,父节点维护的是它代表的区间里的数出现的次数的和 权值线段树基本操作 其实权值线段树的基本操作与线段树没有太大的不同 建树 注意:由于一个叶子节点代表一个数出现的次数,所以,在数的范围非常大时,我们常常需要把这些数排个序,按排序重新赋值(因为权值线段树里数本身的值不重要,我们只需要关注它出现的次数),这也叫做离散化 void build(int l,int r