zoukankan      html  css  js  c++  java
  • 【BZOJ2770】YY的Treap 结论+线段树

    【BZOJ2770】YY的Treap

    Description

    志向远大的YY小朋友在学完快速排序之后决定学习平衡树,左思右想再加上SY的教唆,YY决定学习Treap。友爱教教父SY如砍瓜切菜般教会了YY小朋友Treap(一种平衡树,通过对每个节点随机分配一个priority,同时保证这棵平衡树关于priority是一个小根堆以保证效率)。这时候不怎么友爱的510跑了出来,他问了YY小朋友一个极不和谐的问题:怎么求Treap中两个点之间的路径长度。YY秒了之后决定把这个问题交给你来做,但只要求出树中两点的LCA。

    Input

    第一行两个整数n,m

    第二行n个整数表示每个元素的key

    第三行n个整数表示每个元素的priority

    接下m行,每行一条命令

    I A B,插入一个元素,key为A, priority为B

    D A,删除一个元素,key为A

    Q A B,询问key分别为A和B的LCA的key

    Output

    对于每个Q输出一个整数。

    Sample Input

    2 2
    1 2
    4 5
    Q 1 2
    I 3 3

    Sample Output

    1

    HINT

    数据保证n<=10^5,m<=3*10^5

    其余整数均不超过long的范围

    数据保证任意时刻树中key和priority均不相同

    题解:上来的第一直觉就是猜结论:Treap中a和b的LCA就是key值在a,b之间的,priority最小的点。一开始还想了想怎么证,后来发现这么显然的结论还用证~

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define lson x<<1
    #define rson x<<1|1
    using namespace std;
    typedef long long ll;
    const int maxn=400010;
    int n,m,nm,tot;
    int s[maxn<<2];
    int op[maxn],pa[maxn];
    ll pr[maxn],pb[maxn],ref[maxn],v[maxn];
    char str[10];
    struct node
    {
    	ll val;
    	int org;
    }p[maxn<<1];
    inline int MN(int a,int b)
    {
    	return v[a]<v[b]?a:b;
    }
    bool cmp(const node &a,const node &b)
    {
    	return a.val<b.val;
    }
    void build(int l,int r,int x)
    {
    	if(l==r)
    	{
    		s[x]=l;
    		return ;
    	}
    	int mid=(l+r)>>1;
    	build(l,mid,lson),build(mid+1,r,rson);
    	s[x]=MN(s[lson],s[rson]);
    }
    void updata(int l,int r,int x,int y)
    {
    	if(l==r)	return ;
    	int mid=(l+r)>>1;
    	if(y<=mid)	updata(l,mid,lson,y);
    	else	updata(mid+1,r,rson,y);
    	s[x]=MN(s[lson],s[rson]);
    }
    int query(int l,int r,int x,int a,int b)
    {
    	if(a<=l&&r<=b)	return s[x];
    	int mid=(l+r)>>1;
    	if(b<=mid)	return query(l,mid,lson,a,b);
    	if(a>mid)	return query(mid+1,r,rson,a,b);
    	return MN(query(l,mid,lson,a,b),query(mid+1,r,rson,a,b));
    }
    inline ll rd()
    {
    	ll ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    int main()
    {
    	n=rd(),m=rd();
    	int i;
    	for(i=1;i<=n;i++)	p[++tot].val=rd(),p[tot].org=i;
    	for(i=1;i<=n;i++)	pr[i]=rd();
    	for(i=1;i<=m;i++)
    	{
    		scanf("%s",str);
    		if(str[0]=='I')	op[i]=0,p[++tot].val=rd(),p[tot].org=i+n,pb[i]=rd();
    		if(str[0]=='D')	op[i]=1,p[++tot].val=rd(),p[tot].org=i+n;
    		if(str[0]=='Q')	op[i]=2,p[++tot].val=rd(),p[tot].org=i+n,p[++tot].val=rd(),p[tot].org=i+n;
    	}
    	sort(p+1,p+tot+1,cmp);
    	ref[0]=-1ll<<60;
    	for(i=1;i<=tot;i++)
    	{
    		if(p[i].val>ref[nm])	ref[++nm]=p[i].val,v[nm]=1ll<<60;
    		if(p[i].org<=n)	v[nm]=pr[p[i].org];
    		else
    		{
    			p[i].org-=n;
    			if(op[p[i].org]==0)	pa[p[i].org]=nm;
    			if(op[p[i].org]==1)	pa[p[i].org]=nm;
    			if(op[p[i].org]==2)
    			{
    				if(!pa[p[i].org])	pa[p[i].org]=nm;
    				else	pb[p[i].org]=nm;
    			}
    		}
    	}
    	build(1,nm,1);
    	for(i=1;i<=m;i++)
    	{
    		if(op[i]==0)	v[pa[i]]=pb[i],updata(1,nm,1,pa[i]);
    		if(op[i]==1)	v[pa[i]]=1ll<<60,updata(1,nm,1,pa[i]);
    		if(op[i]==2)	printf("%lld
    ",ref[query(1,nm,1,pa[i],pb[i])]);
    	}
    	return 0;
    }
  • 相关阅读:
    用getBoundingClientRect()来获取页面元素的位置
    asp.net 发送邮件
    MVC5笔记【一】
    WEB前端组件思想【日历】
    WEB前端组件思想【分页】
    【转】前端进阶之路:如何高质量完成产品需求开发
    KindeEditor图片上传插件用法
    jQuery Post 提交内容中有标签报错
    【转发】彻底理解 JS 中 this 的指向
    chrome扩展程序开发之在目标页面运行自己的JS
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7559956.html
Copyright © 2011-2022 走看看