zoukankan      html  css  js  c++  java
  • BZOJ-3065 带插入区间K小值

    这道题为树套树,我自己是替罪羊树套权值线段树。

    此题有三种操作:

    1.询问K值:可通过替罪羊树提取区间+权值线段树合并+二分答案求得

    2.修改:可通过权值线段树的删除+添加操作实现

    3.插入:可通过替罪羊树的插入操作实现

    #include <cstdlib>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #include <cctype>
    #define rep(i, l, r) for(int i=l; i<=r; i++)
    #define clr(x, c) memset(x, c, sizeof(x))
    #define inf 0x7fffffff
    #define ll long long
    #define maxn 80010
    #define maxl 70010
    
    #define l(x) Left[x]
    #define r(x) Right[x]
    #define s(x) Size[x]
    #define k(x) Key[x]
    #define t(x) Tree[x]
    #define ls(x) Size[Left[x]]
    #define rs(x) Size[Right[x]]
    #define a 0.8
    
    using namespace std;
    inline int read()
    {
    	int x=0, f=1; char ch=getchar();
    	while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    	while (isdigit(ch)) x=x*10+ch-'0', ch=getchar();
    	return x*f;
    }
    
    //=========================================================================================
    
    struct node
    {
    	node *l, *r; int sum;
    	node () {sum=0; l=r=NULL;}
    } *blank=new(node);
    void Add(int l, int r, int k, node*&t)
    {
    	if (t==blank) t=new(node), t->l=t->r=blank;
    	t->sum++;
    	if (l==r) return; int mid=(l+r)>>1;
    	if (k<=mid) Add(l, mid, k, t->l); else Add(mid+1, r, k, t->r);
    }
    void Del(int l, int r, int k, node*&t)
    {
    	t->sum--;
    	if (l==r) return; int mid=(l+r)>>1;
    	if (k<=mid) Del(l, mid, k, t->l); else Del(mid+1, r, k, t->r);
    }
    
    //=========================================================================================
    
    int Left[maxn], Right[maxn], Key[maxn], Size[maxn], V=0, roof, dfn[maxn], top;
    node *Tree[maxn];
    void Build(int l, int r, int &t)
    {
    	if (l>r) {t=0; return;}
    	int mid=(l+r)>>1; 
    	t=dfn[mid], t(t)=blank, s(t)=r-l+1;
    	rep(i, l, r) Add(0, maxl, k(dfn[i]), t(t));
    	Build(l, mid-1, l(t)), Build(mid+1, r, r(t));
    }
    node *range[maxn];
    int p[maxn], nr, np;
    void ranging(int l, int r, int t) //BST查找区间
    {
    	if (r<ls(t)) ranging(l, r, l(t));  //全在左边
    	else if (l>ls(t)) ranging(l-ls(t)-1, r-ls(t)-1, r(t)); //全在右边
    	else if (!l && r==s(t)-1) range[++nr]=t(t); //整棵树都是
    	else //分跨两边
    	{
    		p[++np]=k(t);
    		if (l<ls(t)) ranging(l, ls(t)-1, l(t));
    		if (r>ls(t)) ranging(0, r-ls(t)-1, r(t));
    	}
    }
    void getrange(int l, int r){nr=np=0; ranging(l-1, r-1, roof);} 
    void dfs(int t){if (l(t)) dfs(l(t)); dfn[++top]=t; if (r(t)) dfs(r(t));} //DFS序
    void Recycle(node *t)  //回收节点
    {
    	if (!t->sum) return;
    	if (t->l) Recycle(t->l);
    	if (t->r) Recycle(t->r);
    	delete(t);
    }
    void reBuild(int &t)
    {
    	top=0; dfs(t); 
    	rep(i, 1, top) Recycle(t(dfn[i])); 
    	Build(1, top, t);
    }
    
    //=========================================================================================
    
    bool Insert(int r, int k, int h, int &t)
    {
    	if (!t)
    	{
    		t=++V;
    		s(t)=1, k(t)=k, l(t)=r(t)=0, t(t)=blank;
    		Add(0, maxl, k, t(t));
    		return h>log(V)/log(1/a);
    	}
    	bool flag;
    	if (r<=ls(t)) 
    		flag=Insert(r, k, h+1, l(t));
    	else flag=Insert(r-ls(t)-1, k, h+1, r(t));
    	s(t)=ls(t)+rs(t)+1; Add(0, maxl, k, t(t));
    	if (flag && (max(ls(t), rs(t)) > a*s(t))) {reBuild(t); return false;}
    	return flag;
    }
    int Change(int r, int k, int t)
    {
    	if (ls(t)==r)
    	{
    		int v=k(t);
    		Del(0, maxl, k(t), t(t));
    		Add(0, maxl, k(t)=k, t(t));
    		return v;
    	}
    	int v;
    	if (r<ls(t)) v=Change(r, k, l(t));
    	else v=Change(r-ls(t)-1, k, r(t));
    	Del(0, maxl, v, t(t));
    	Add(0, maxl, k, t(t));
    	return v;
    }
    int Query(int l, int r, int rank)
    {
    	rank--;
    	getrange(l, r);
    	int L=0, R=maxl;
    	while (L<R)
    	{
    		int mid=(L+R)>>1, sum=0;
    		rep(i, 1, nr) sum+=range[i]->l->sum;
    		rep(i, 1, np) sum+=(p[i]>=L && p[i]<=mid) ? 1 : 0;
    		if (rank<sum)
    			{rep(i, 1, nr) range[i]=range[i]->l; R=mid;}
    		else
    			{rank-=sum; rep(i, 1, nr) range[i]=range[i]->r; L=mid+1;}
    	}
    	return L;
    }
    
    //=========================================================================================
    
    int n, m, w[maxn], last=0;
    int main()
    {
    	blank->l=blank->r=blank;
    	n=read(); rep(i, 1, n) w[i]=read();
    	l(0)=r(0)=s(0)=0;
    	rep(i, 1, n) dfn[i]=++V, k(V)=w[i];
    	Build(1, n, roof);
    	m=read();
    	while (m--)
    	{
    		char ch=getchar(); while (ch!='Q' && ch!='M' && ch!='I') ch=getchar();
    		if (ch=='Q')
    		{
    			int x=read()^last, y=read()^last, z=read()^last;
    			printf("%d
    ", last=Query(x, y, z));
    		}
    		else if (ch=='I')
    		{
    			int x=read()^last, y=read()^last;
    			Insert(x-1, y, 0, roof);
    		}
    		else
    		{
    			int x=read()^last, y=read()^last;
    			Change(x-1, y, roof);
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    LeetCode 326. Power of Three
    LeetCode 324. Wiggle Sort II
    LeetCode 322. Coin Change
    LeetCode 321. Create Maximum Number
    LeetCode 319. Bulb Switcher
    LeetCode 318. Maximum Product of Word Lengths
    LeetCode 310. Minimum Height Trees (DFS)
    个人站点大开发!--起始篇
    LeetCode 313. Super Ugly Number
    LeetCode 309. Best Time to Buy and Sell Stock with Cooldown (DP)
  • 原文地址:https://www.cnblogs.com/NanoApe/p/4445374.html
Copyright © 2011-2022 走看看