zoukankan      html  css  js  c++  java
  • BZOJ 3196 Tyvj 1730 二逼平衡树:线段树套splay

    传送门

    题意

    给你一个长度为 $ n $ 有序数列 $ a $ ,进行 $ m $ 次操作,操作有如下几种:

    1. 查询 $ k $ 在区间 $ [l,r] $ 内的排名
    2. 查询区间 $ [l,r] $ 内排名为 $ k $ 的值
    3. 将 $ a[p] $ 修改为 $ k $
    4. 查询 $ k $ 在区间 $ [l,r] $ 内的前驱(前驱定义为小于 $ k $ ,且最大的数)
    5. 查询 $ k $ 在区间 $ [l,r] $ 内的后继(后继定义为大于 $ k $ ,且最小的数)

    题解

    线段树套splay。

    先将 $ n $ 个数插入线段树:对于每个 $ a[i] $,将线段树上到位置 $ i $ 的叶子节点的路径上的所有splay插入元素 $ a[i] $ 。

    操作1:区间 $ [l,r] $ 在线段树上对应了若干棵splay,将这些splay中小于 $ k $ 的元素个数累加,记为 $ sum $ ,$ sum+1 $ 即为答案。

    操作2:二分这个元素的值,然后进行操作1得到当前rank,对应地调整答案。

    操作3:将线段树上到位置 $ p $ 的叶子节点的路径上的所有splay删除 $ a[p] $ ,再插入 $ k $ ,然后更新 $ a[p] = k $ 。

    操作4:将区间 $ [l,r] $ 对应的所有splay中查询到的 $ k $ 的前驱取 $ max $ 即可。

    操作5:将区间 $ [l,r] $ 对应的所有splay中查询到的 $ k $ 的后继取 $ min $ 即可。

    最后,纪念一下我用pbds加map封装的的假splay......QAQ

    还有就是因为b站g++版本太老,null_type会CE,要改成null_mapped_type

    AC Code

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <ext/pb_ds/assoc_container.hpp>
    #include <ext/pb_ds/tree_policy.hpp>
    #define MAX_N 50005
    #define MAX_V 200005
    #define INF 2147483647
    
    using namespace std;
    using namespace __gnu_pbds;
    
    typedef tree<pair<int,int>,null_mapped_type,less<pair<int,int> >,rb_tree_tag,tree_order_statistics_node_update> Tree;
    typedef Tree::iterator git;
    
    struct Splay
    {
    	Tree t;
    	map<int,int> mp;
    	void ins(int x)
    	{
    		t.insert(make_pair(x,mp[x]=mp[x]+1));
    	}
    	void del(int x)
    	{
    		t.erase(make_pair(x,mp[x])),mp[x]=mp[x]-1;
    	}
    	int pre(int x)
    	{
    		if(t.empty()) return -INF;
    		git it=t.lower_bound(make_pair(x,0));
    		if(it==t.begin()) return -INF;
    		return (--it)->first;
    	}
    	int suc(int x)
    	{
    		if(t.empty()) return INF;
    		git it=t.upper_bound(make_pair(x,INF));
    		if(it==t.end()) return INF;
    		return it->first;
    	}
    	int kth(int x)
    	{
    		return t.find_by_order(x-1)->first;
    	}
    	int rk(int x)
    	{
    		return t.order_of_key(make_pair(x,1))+1;
    	}
    };
    
    int n,m;
    int a[MAX_N];
    Splay t[MAX_V];
    
    void ins(int p,int k,int l,int r,int x)
    {
    	t[k].ins(x);
    	if(l==r) return;
    	int mid=(l+r)>>1;
    	if(p<=mid) ins(p,k*2+1,l,mid,x);
    	else ins(p,k*2+2,mid+1,r,x);
    }
    
    int getrk(int a,int b,int k,int l,int r,int x)
    {
    	if(a<=l && r<=b) return t[k].rk(x)-1;
    	int mid=(l+r)>>1,ans=0;
    	if(a<=mid) ans+=getrk(a,b,k*2+1,l,mid,x);
    	if(b>mid) ans+=getrk(a,b,k*2+2,mid+1,r,x);
    	return ans;
    }
    
    int getx(int a,int b,int k)
    {
    	int l=0,r=INF;
    	while(r-l>1)
    	{
    		int mid=(l+r)>>1;
    		if(getrk(a,b,0,1,n,mid)<=k-1) l=mid;
    		else r=mid;
    	}
    	return l;
    }
    
    void upd(int p,int k,int l,int r,int x)
    {
    	t[k].del(a[p]),t[k].ins(x);
    	if(l==r) return;
    	int mid=(l+r)>>1;
    	if(p<=mid) upd(p,k*2+1,l,mid,x);
    	else upd(p,k*2+2,mid+1,r,x);
    }
    
    int getpre(int a,int b,int k,int l,int r,int x)
    {
    	if(a<=l && r<=b) return t[k].pre(x);
    	int mid=(l+r)>>1,ans=-INF;
    	if(a<=mid) ans=max(ans,getpre(a,b,k*2+1,l,mid,x));
    	if(b>mid) ans=max(ans,getpre(a,b,k*2+2,mid+1,r,x));
    	return ans;
    }
    
    int getsuc(int a,int b,int k,int l,int r,int x)
    {
    	if(a<=l && r<=b) return t[k].suc(x);
    	int mid=(l+r)>>1,ans=INF;
    	if(a<=mid) ans=min(ans,getsuc(a,b,k*2+1,l,mid,x));
    	if(b>mid) ans=min(ans,getsuc(a,b,k*2+2,mid+1,r,x));
    	return ans;
    }
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++) scanf("%d",&a[i]),ins(i,0,1,n,a[i]);
    	int opt,l,r,k,p;
    	while(m--)
    	{
    		scanf("%d",&opt);
    		if(opt==1)
    		{
    			scanf("%d%d%d",&l,&r,&k);
    			printf("%d
    ",getrk(l,r,0,1,n,k)+1);
    		}
    		if(opt==2)
    		{
    			scanf("%d%d%d",&l,&r,&k);
    			printf("%d
    ",getx(l,r,k));
    		}
    		if(opt==3)
    		{
    			scanf("%d%d",&p,&k);
    			upd(p,0,1,n,k),a[p]=k;
    		}
    		if(opt==4)
    		{
    			scanf("%d%d%d",&l,&r,&k);
    			printf("%d
    ",getpre(l,r,0,1,n,k));
    		}
    		if(opt==5)
    		{
    			scanf("%d%d%d",&l,&r,&k);
    			printf("%d
    ",getsuc(l,r,0,1,n,k));
    		}
    	}
    }
    
  • 相关阅读:
    lr 增强窗格中,如何生成调试信息?
    lr 自带的例子,如何进行关联,通过代码的函数进行实现
    lr11 录制脚本时候,无法自动启动ie,查了网上很多方法都未解决?
    loadrunner11 录制脚步不成功,在录制概要出现“No Events were detected”,浮动窗口总是显示“0 Events”,解决办法
    loadrunner11 安装及破解教程来自百度文库
    安装loadrunner11 ,出现如下错误如何解决?
    回收站数据删除了,如何进行恢复?
    网管工作方面——————打印机删除了然后开机重启他依然存在,如何解决
    Windows 不能在 本地计算机 启动 SQL Server 服务 错误代码126
    Sorry, the page you are looking for is currently unavailable. Please try again later. Nginx
  • 原文地址:https://www.cnblogs.com/Leohh/p/9205400.html
Copyright © 2011-2022 走看看