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;
    }
  • 相关阅读:
    LeetCode 258 Add Digits
    LeetCode 231 Power of Two
    LeetCode 28 Implement strStr()
    LeetCode 26 Remove Duplicates from Sorted Array
    LeetCode 21 Merge Two Sorted Lists
    LeetCode 20 Valid Parentheses
    图形处理函数库 ImageTTFBBox
    php一些函数
    func_get_arg(),func_get_args()和func_num_args()的用法
    人生不是故事,人生是世故,摸爬滚打才不会辜负功名尘土
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7559956.html
Copyright © 2011-2022 走看看