• 线段树 [HZOI 2015]聪聪的世界


    背景:

    聪聪的性取向有问题。

    题目描述:

    聪聪遇到了一个难题:

    给出一个序列a1…an,完成以下操作:

    1  x 询问从x向左数第一个<ax的数;

    2  x 询问从x向左数第一个>ax的数;

    3  x 询问从x向右数第一个<ax的数;

    4  x 询问从x向右数第一个>ax的数;

    5  x y 交换ax与ay;

    6  x y w 给ax…ay加上w;

    7  x y w 给ax…ay减去w。

    聪聪急切的想知道答案,因为他完成任务后就可以迎娶高富帅,出任CEO,走上人生巅峰,成为人生赢家!

    请你帮帮他。

    【输入格式】

    第一行 n,m。

    第二行 a1…an。

    第三行到m+2行为以上七个操作。

    【输出格式】

    对于每个op>=1且op<=4输出一行表示答案,无解输出-1。

    【样例输入】

    5 5

    8 2 0 0 9

    1 2

    5 1 3

    7 1 3 1

    4 2

    1 1

    【样例输出】

    -1

    7

    -1

    【提示】


    10%  n,m<=10000

    40%  n,m<=100000

    100%  n,m<=1000000

    对于所有输入的数保证在[0,10^9]范围内

        注:聪聪,出题人和高富帅都是往届大佬
        要求一个点最靠近它且大于(小于)的值,有两种考虑方法,一是记录所查节点的位置,从根往下搜,
        以找右边较大为例,在左子树下标大于所查点的前提下,尽量往左子树走,否则向右子树。
        就这么干找。。。
        第二种方法,(我打的就是这种非主流。。)从叶子节点往上找,
        同样以右边较大为例,
        如果在左子树,而右子树有大于它的,去右子树向下搜,否则爬向父亲。
        如果在右子树,直接爬到父亲(因为无法向下走了)
        而在向下走时,同样,尽量走左子树,否则走右子树。
        向左走反之。
        最重要的是本题涉及lazy操作,什么时候要传的计算好,我就不写了。
       
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #define ll long long
    #define N 1000000
    using namespace std;
    ll n,m,a[N+5],b[N+5];
    struct node
    {
    	ll l,r,h,k,lazy;
    } t[4*N+5];
    ll read()
    {
    	ll sum=0,f=1;char x=getchar();
    	while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();}
    	while(x>='0'&&x<='9'){sum=sum*10+x-'0';x=getchar();}
    	return sum*f;
    }
    inline void pushup(ll x)
    {
    	t[x].h=max(t[x*2].h,t[x*2+1].h);
    	t[x].k=min(t[x*2].k,t[x*2+1].k);
    }
    inline void pushdown(ll x)
    {
    	ll l=t[x].lazy;
    	t[x*2].h+=l;t[x*2].k+=l;t[x*2].lazy+=l;
    	t[x*2+1].h+=l;t[x*2+1].k+=l;t[x*2+1].lazy+=l;
    	t[x].lazy=0;
    }
    inline void build(ll l,ll r,ll x)
    {
    	t[x].l=l;t[x].r=r;t[x].lazy=0;
    	if(l==r)
    	{
    		t[x].k=t[x].h=a[l];
    		b[l]=x;
    		return ;
    	}
    	ll mid=(l+r)/2;
    	build(l,mid,x*2);
    	build(mid+1,r,x*2+1);
    	pushup(x);
    }
    inline void pllus(ll l,ll r,ll k,ll x)
    {
    	if(t[x].l>=l&&t[x].r<=r)
    	{
    		t[x].h+=k;t[x].k+=k;
    		t[x].lazy+=k;
    		return;
    	}
    	if(t[x].lazy)pushdown(x);
    	ll mid=(t[x].l+t[x].r)/2;
    	if(l<=mid) pllus(l,r,k,x*2);
    	if(r>mid) pllus(l,r,k,x*2+1);
    	if(t[x].l!=t[x].r)
    	pushup(x);
    }
    void wohh(ll x)
    {
    	if(x!=1)
    	    wohh(x/2);
    	if(t[x].lazy&&t[x].l!=t[x].r)
    	    pushdown(x);
    }
    inline void change(ll x,ll y)
    {
        ll f;
        wohh(b[x]);
        wohh(b[y]);
        f=t[b[x]].h;
        pllus(x,x,t[b[y]].h-t[b[x]].h,1);
        pllus(y,y,f-t[b[y]].h,1);
    }
    inline ll min_ldown(ll k,ll x)
    {
    	if(t[x].l==t[x].r)
    	   return t[x].h;
    	if(t[x].lazy&&t[x].l!=t[x].r)pushdown(x);
    	if(t[x*2+1].k<k)
    	    return min_ldown(k,x*2+1);
    	else
    	    return min_ldown(k,x*2);
    }
    inline ll min_lup(ll k,ll x)
    {
    	if(x==1)return -1;
        if(x&1)
        {
        	if(t[x^1].k<k)
        	    return min_ldown(k,x^1);
        	else
        	    return min_lup(k,x/2);
    	}
    	else
    	    return min_lup(k,x/2);
    }
    inline ll min_rdown(ll k,ll x)
    {
    	if(t[x].l==t[x].r)
    	   return t[x].h;
    	if(t[x].lazy&&t[x].l!=t[x].r)pushdown(x);
    	if(t[x*2].k<k)
    	    return min_rdown(k,x*2);
    	else
    	    return min_rdown(k,x*2+1);
    }
    inline ll min_rup(ll k,ll x)
    {
    	if(x==1)return -1;
        if(!(x&1))
        {
        	if(t[x^1].k<k)
        	    return min_rdown(k,x^1);
        	else
        	    return min_rup(k,x/2);
    	}
    	else
    	    return min_rup(k,x/2);
    }
    inline ll max_rdown(ll k,ll x)
    {
    	if(t[x].l==t[x].r)
    	   return t[x].h;
    	if(t[x].lazy&&t[x].l!=t[x].r)pushdown(x);
    	if(t[x*2].h>k)
    	    return max_rdown(k,x*2);
    	else
    	    return max_rdown(k,x*2+1);
    }
    inline ll max_rup(ll k,ll x)
    {
    	if(x==1)return -1;
        if(!(x&1))
        {
        	if(t[x^1].h>k)
        	    return max_rdown(k,x^1);
        	else
        	    return max_rup(k,x/2);
    	}
    	else
    	    return max_rup(k,x/2);
    }
    inline ll max_ldown(ll k,ll x)
    {
    	if(t[x].l==t[x].r)
    	   return t[x].h;
    	if(t[x].lazy&&t[x].l!=t[x].r)pushdown(x);
    	if(t[x*2+1].h>k)
    	    return max_ldown(k,x*2+1);
    	else
    	    return max_ldown(k,x*2);
    }
    inline ll max_lup(ll k,ll x)
    {
    	if(x==1)return -1;
        if((x&1))
        {
        	if(t[x^1].h>k)
        	    return max_ldown(k,x^1);
        	else
        	    return max_lup(k,x/2);
    	}
    	else
    	    return max_lup(k,x/2);
    }
    int yjn()
    {
    	freopen("ccsworld.in","r",stdin);
    	freopen("ccsworld.out","w",stdout);
    	n=read();m=read();
    	ll op,x,y,z;
    	for(ll i=1;i<=n;i++)a[i]=read();
    	build(1,n,1);
    	while(m--)
    	{
    		op=read();x=read();
    		switch(op)
    		{
    		    case 1 :wohh(b[x]);printf("%lld\n",min_lup(t[b[x]].h,b[x]));break;
    		    case 2 :wohh(b[x]);printf("%lld\n",max_lup(t[b[x]].h,b[x]));break;
        		case 3 :wohh(b[x]);printf("%lld\n",min_rup(t[b[x]].h,b[x]));break;
    			case 4 :wohh(b[x]);printf("%lld\n",max_rup(t[b[x]].h,b[x]));break;
    			case 5 :y=read();change(x,y);break;
    			case 6 :y=read();z=read();pllus(x,y,z,1);break;
    			case 7 :y=read();z=read();pllus(x,y,-z,1);break;
    		}
            
    	}
    }
    int qty=yjn();
    int main(){;}

  • 相关阅读:
    I.MX6ULL LED C程序(转自左忠凯)
    I.MX6ULL的LED汇编程序
    Linux中的信号
    springboot的模板引擎之简介区分(一)
    springboot常用Starter介绍
    springboot拦截器之Filter和拦截器Interceptor之间的区别(六)
    springboot拦截器之多个自定义拦截器Interceptor的执行顺序(五)
    springboot拦截器之自定义拦截器Interceptor以及新旧配置的对比(四)
    springboot拦截器之自定义监听器listener(三)
    springboot拦截器之自定义原生servlet(二)
  • 原文地址:https://www.cnblogs.com/QTY2001/p/7632746.html
Copyright © 2020-2023  润新知