您的位置:首页 > 其它

[bzoj]-1901-Zju2112 Dynamic Rankings-可持久化线段树

2015-03-03 11:06 253 查看
动态查询区间第K大值,单点修改,树状数组套可持久化线段树,线段树中每个代表的相同区间的节点组成了一个树状数组,这样就可以logn的查询前缀和了。

写了好长时间,调了好长时间,毕竟蒟蒻

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 110086
using namespace std;

struct node
{
	int l, r, s;
}t[maxn * 30];

int n, m, num, root[maxn], a[maxn >> 1], b[maxn], dat[maxn >> 1][4], size, cnt, lc, rc, ln[maxn], rn[maxn];

void build(int &x, int l, int r)
{
	x = ++cnt;
	t[x].s = 0;
	if (l == r)
		return ;
	int mid = (l + r) >> 1;
	build(t[x].l, l, mid);
	build(t[x].r, mid + 1, r);
	return ;
}

void update(int &x, int l, int r, int pos, int v)
{
	t[++cnt] = t[x];
	x = cnt;
	t[x].s += v;
	if (l == r)
		return ;
	int mid = (l + r) >> 1;
	if (pos <= mid)
		update(t[x].l, l, mid, pos, v);
	else
		update(t[x].r, mid + 1, r, pos, v);
	return ;
}

void mutiupdate(int x, int pos, int v)
{
	while (x <= n)
	{
		update(root[x], 1, num, pos, v);
		x += x & -x;
	}
	return ;
}

int query(int k)
{
	int l = 1, r = num, tl, tr;
	while (l != r)
	{
		tl = tr = 0;
		for (int i = 1; i <= lc; i++)
        	tl += t[ t[ ln[i] ].l ].s;
        for (int i = 1; i <= rc; i++)
			tr += t[ t[ rn[i] ].l ].s;
        if (tr - tl >= k)
		{
            for (int i = 1; i <= lc; i++)
				ln[i] = t[ ln[i] ].l;
            for (int i = 1; i <= rc; i++)
				rn[i] = t[ rn[i] ].l;
            r = (l + r) >> 1;
        }
        else
		{
        	for (int i = 1; i <= lc; i++)
            	ln[i] = t[ ln[i] ].r;
            for (int i = 1; i <= rc; i++)
				rn[i] = t[ rn[i] ].r;
            l = (l + r >> 1) + 1;
			k -= tr - tl; 
        }
		
	}
	return l;
}

int getans(int l, int r, int k)
{
	lc = rc = 0;
	while (l)
	{
		ln[++lc] = root[l];
		l -= l & -l;
	}
	while (r)
	{
		rn[++rc] = root[r];
		r -= r & -r;
	}
	return query(k);
}

void solve()
{
    sort( b + 1, b + size + 1);
    num = unique(b + 1, b + size + 1) - b - 1;
    for (int i = 1; i <= n; i++) 
		a[i] = lower_bound(b + 1, b + num + 1, a[i]) - b;
    build(root[0], 1, num);
    for (int i = 1; i <= n; i++)
		mutiupdate(i, a[i], 1);
    for (int i = 1; i <= m; i++)
	{
        if(dat[i][0] == 0)
			printf("%d\n", b[ getans(dat[i][1] - 1, dat[i][2], dat[i][3]) ]);
        else
		{
            int pos = lower_bound(b + 1, b + num + 1, dat[i][2]) - b;
            mutiupdate(dat[i][1], a[dat[i][1]], -1);
            a[dat[i][1]] = pos;
            mutiupdate(dat[i][1], a[dat[i][1]], 1);
        }
    }
}

int main()
{
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++)
	{
		scanf("%d", &a[i]);
		b[++size] = a[i];
	}
	char cmd[3];
	for (int i = 1; i <= m; i++)
	{
		scanf("%s", cmd);
		if (cmd[0] == 'C')
		{
			dat[i][0] = 1;
			scanf("%d %d",&dat[i][1], &dat[i][2]);
			b[++size] = dat[i][2];
		}
		else
		{
			dat[i][0] = 0;
			scanf("%d %d %d", &dat[i][1], &dat[i][2], &dat[i][3]);
		}
	}
	solve();
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: