【主席树】【bzoj 1901】: Zju2112 Dynamic Rankings

http://www.lydsy.com/JudgeOnline/problem.php?id=1901


Orz 主席!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

这主席树理解起来真tm困难,用BIT来套,就不想说什么了

开始想的动态开点,就没有离散化,结果二分的时候可能慢一点


update

今天下午想了一下,发现主席树不难嘛

空间O(nlognlogn)有点吃紧

树状数组每个点维护个前缀,把树状数组询问的点保存起来就可以了

为什么树套树的复杂度多了一个log捏,我今天才知道

可持久化线段树还有一个性质是平衡树不具备的

——每棵树的结构相同,这样就可以整体操作了


//#define _TEST _TEST
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
/************************************************
Code By willinglive    Blog:http://willinglive.cf
************************************************/
#define rep(i,l,r) for(int i=l,___t=(r);i<=___t;i++)
#define per(i,r,l) for(int i=r,___t=(l);i>=___t;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define LL long long
#define INE(i,u,e) for(int i=head[u];~i;i=e[i].next)
inline const int read()
{
    int r=0,k=1;char c=getchar();
    for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
    for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';
    return k*r;
}
/
int n,m;
int a[10010],cnt,b[10010];
int root[10010];
map<int,int>M;
int s[10010];
/
namespace Chair
{///
int sz[4000000],tot;
int ls[4000000],rs[4000000];
void insert(int &o,int L,int R,int x,int val)
{
	if(!o) o=++tot;
	sz[o]+=val;
	if(L==R) return;
	int mid=L+R>>1;
	if(x<=mid) insert(ls[o],L,mid,x,val);
	else insert(rs[o],mid+1,R,x,val);
}
}///
namespace BIT
{///
void add(int o,int x,int val)
{
	for(;o<=n;o+=o&-o) Chair::insert(root[o],0,1000000000,x,val);
}
void query(int x,int y,int k)
{
	using namespace Chair;
	int i,l=0,r=1000000000,mid;
	int top=0,topr;
	for(i=y;i;i-=i&-i) s[++top]=root[i]; //[1,topr]
	topr=top;
	for(i=x-1;i;i-=i&-i) s[++top]=root[i]; //[topr+1,top]
	while(l<r)
	{
		mid=l+r>>1;
		int res=0;
		rep(i,1,topr) res+=sz[ls[s[i]]];
		rep(i,topr+1,top) res-=sz[ls[s[i]]];
		if(res>=k)
		{
			r=mid;
			rep(i,1,top) s[i]=ls[s[i]];
		}
		else
		{
			l=mid+1;
			k-=res;
			rep(i,1,top) s[i]=rs[s[i]];
		}
	}
	printf("%d\n",l);
}
}///
/
void input()
{
    n=read(); m=read();
    rep(i,1,n) a[i]=read();
}
void solve()
{
	using namespace BIT;
	char op[3];int l,r,k;
    rep(i,1,n) add(i,a[i],1);
    rep(i,1,m)
    {
    	scanf("%s",op); l=read(); r=read();
    	if(op[0]=='C')
    	{
    		add(l,a[l],-1);
    		add(l,r,1);
    		a[l]=r;
    	}
    	else
    	{
    		k=read();
    		query(l,r,k);
    	}
    }
}
/
int main()
{
    #ifndef _TEST
    freopen("std.in","r",stdin); freopen("std.out","w",stdout);
    #endif
    input(),solve();
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值