BZOJ 1901 Zju 2112 Dynamic Rankings 带修改主席树

题目大意:给出一个序列,单点修改,询问区间第k大。

思路:如果不带修改,那么划分树就可以解决,但是划分树是静态的树,不支持修改。带修改的主席舒其实就是外层fenwick套内层权值线段树,但是权值线段树必须动态开节点。然后修改的时候就像树状数组修改那样,每次修改logn个权值线段树。查询的时候也一样,返回logn个权值线段树统计的和。

最后为了求区间第k大,还需要二分答案。

CODE:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 10010
#define MAX_RANGE 1000000000
using namespace std;

struct Complex{
	Complex *son[2];
	int num;
	Complex() {
		son[0] = son[1] = NULL;
		num = 0;
	}
}*fenwick[MAX];

int cnt,asks;
int src[MAX];

char c[10];

inline void Fix(int x,int c);
inline void _Fix(int x,int c);
inline int GetSum(int x,int k);

void Insert(Complex *&a,int l,int r,int x);
void Delete(Complex *&a,int l,int r,int x);
int Ask(Complex *a,int l,int r,int k);

int Ask(int x,int y,int k);

int main()
{
	cin >> cnt >> asks;
	for(int i = 1;i <= cnt; ++i) {
		scanf("%d",&src[i]);
		Fix(i,src[i]);
	}
	for(int x,y,z,i = 1;i <= asks; ++i) {
		scanf("%s",c);
		if(c[0] == 'Q') {
			scanf("%d%d%d",&x,&y,&z);
			printf("%d\n",Ask(x,y,z));
		}
		else {
			scanf("%d%d",&x,&y);
			_Fix(x,src[x]);
			Fix(x,src[x] = y);
		}
	}
	return 0;
}

inline void Fix(int x,int c)
{
	for(;x <= cnt;x += x&-x)
		Insert(fenwick[x],0,MAX_RANGE,c);
}

inline void _Fix(int x,int c)
{
	for(;x <= cnt;x += x&-x)
		Delete(fenwick[x],0,MAX_RANGE,c);
}

inline int GetSum(int x,int k)
{
	int re = 0;
	for(;x;x -= x&-x)
		re += Ask(fenwick[x],0,MAX_RANGE,k);
	return re;
}

int Ask(int x,int y,int k)
{
	int l = 0,r = MAX_RANGE,ans = 0;
	while(l <= r) {
		int mid = (l + r) >> 1;
		int temp = GetSum(y,mid) - GetSum(x - 1,mid);
		if(temp >= k)
			r = mid - 1,ans = mid;
		else	l = mid + 1;
	}
	return ans;
}

void Insert(Complex *&a,int l,int r,int x)
{
	if(a == NULL)	a = new Complex();
	a->num++;
	if(l == r)	return ;
	int mid = (l + r) >> 1;
	if(x <= mid)	Insert(a->son[0],l,mid,x);
	else	Insert(a->son[1],mid + 1,r,x);
}

void Delete(Complex *&a,int l,int r,int x)
{
	if(!--a->num) {
		free(a);
		a = NULL;
		return ;
	}
	if(l == r)	return ;
	int mid = (l + r) >> 1;
	if(x <= mid)	Delete(a->son[0],l,mid,x);
	else	Delete(a->son[1],mid + 1,r,x);
}

int Ask(Complex *a,int l,int r,int k)
{
	if(a == NULL)	return 0;
	if(l == r)	return a->num;
	int mid = (l + r) >> 1;
	if(k <= mid)	return Ask(a->son[0],l,mid,k);
	else {
		int left = a->son[0] == NULL ? 0:a->son[0]->num;
		return left + Ask(a->son[1],mid + 1,r,k);
	}
}
时间: 2024-10-18 14:27:28

BZOJ 1901 Zju 2112 Dynamic Rankings 带修改主席树的相关文章

BZOJ 1901 Zju 2112 Dynamic Rankings 动态维护第k小 树套树

题目大意:动态维护第k小. 思路:线段树套treap,裸题,就是不怎么好写. CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 50010 #define INF 1e9 #define LEFT (pos << 1) #define RIGHT (pos << 1|1) #define SIZ

zoj 2112 Dynamic Rankings 带修改区间第K大 动态主席树

pass 首先,个人觉得把这个数据结构理解成树状数组套主席树是十分不严谨的.主席树的本质是可持久化权值线段树与前缀和思想的结合.而动态主席树是可持久化权值线段树与树状数组思想的结合.并非树套树般的泾渭分明的叠加. 其次,大概讲下对动态主席树的理解.我们静态主席树中,第i个版本维护的是[1,i]的权值线段树,我们利用前缀和的思想,通过y的版本-x的版本得到[x,y]的权值线段树,从而剥离出一颗对应区间的权值线段树.我们考虑在这个情况下,如果需要修改第a[i]的值,那么从i,i+1,i+2.....

【BZOJ-1901】Dynamic Rankings 带修主席树

1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 7292  Solved: 3038[Submit][Status][Discuss] Description 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i

BZOJ 1146: [CTSC2008]网络管理Network [树上带修改主席树]

1146: [CTSC2008]网络管理Network Time Limit: 50 Sec  Memory Limit: 162 MBSubmit: 3522  Solved: 1041[Submit][Status][Discuss] Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高速光缆组成. 每个部门都有一个专属的路由器,

少年,想学带修改主席树吗 | BZOJ1901 带修改区间第k小

少年,想学带修改主席树吗 | BZOJ1901 带修改区间第k小 有一道题(BZOJ 1901)是这样的:n个数,m个询问,询问有两种:修改某个数/询问区间第k小. 不带修改的区间第k小用主席树很好写,不会的同学可以看一下这个. 加上修改怎么做呢?我们可以用数学老师成天讲的类比思想: 可以发现,不修改的区间k小问题中,每加入一个原序列中的数,对应的主席树在上一个的基础上进行修改,而查询的时候用右端点主席树减去左端点左边的主席树.这样的操作就像是维护前缀和:每次加入一个元素的时候,sum[i] =

ZJU 2112 Dynamic Rankings

Dynamic Rankings Time Limit: 10000ms Memory Limit: 32768KB This problem will be judged on ZJU. Original ID: 211264-bit integer IO format: %lld      Java class name: Main The Company Dynamic Rankings has developed a new kind of computer that is no lon

【模板】 带修改主席树

也就是树状数组加线段树 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=5e4+7; 4 struct node{ 5 int l,r,sum; 6 }tr[N<<3]; 7 struct quer{ 8 int l,r,k,v,op; 9 }q[10000+7]; 10 int rtn,Ln,Rn; 11 int a[N],b[N],rt[N<<2],L[N<<2],R[N<

ZOJ -2112 Dynamic Rankings 主席树 待修改的区间第K大

Dynamic Rankings 带修改的区间第K大其实就是先和静态区间第K大的操作一样.先建立一颗主席树, 然后再在树状数组的每一个节点开线段树(其实也是主席树,共用节点), 每次修改的时候都按照树状数组的方式去修改,并且修改那些地方.查询的时候就是查询原主席树+树状数组的值. 代码: 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r&quo

ZOJ 2112 Dynamic Rankings(主席树の动态kth)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2112 The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. T