• bzoj1251 序列终结者 splay


    又写了一次splay 感觉更有体会 速度居然又卡进了首页。。

    这题要注意初始值应为-inf(mx和v)

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #define rep(i,l,r) for(int i=l;i<r;i++)
    #define clr(a,x) memset(a,x,sizeof(a))
    using namespace std;
    const int maxn=50050,maxm=100050,inf=0x3fffffff;
    int n,m;
    struct node*null,*pt;
    struct node{
        node*ch[2];
        int v,s,add,mx;
        bool rev;
        inline int cmp(int k) const{
            k-=ch[0]->s;
            if(k==1) return -1;
            return k<=0?0:1;
        }
        inline void maintain(){
            s=ch[0]->s+ch[1]->s+1;
            mx=max(v,max(ch[0]->mx,ch[1]->mx));
        }
        inline void pushdown(){
            if(rev){
                rev=0;
                ch[0]->rev^=1;
                ch[1]->rev^=1;
                swap(ch[0],ch[1]);
            }
            if(add){    
                if(ch[0]!=null){
                    ch[0]->add+=add;
                    ch[0]->v+=add;
                    ch[0]->mx+=add;
                }
                if(ch[1]!=null){
                    ch[1]->add+=add;
                    ch[1]->mx+=add;
                    ch[1]->v+=add;
                }
                add=0;
            }
        }
    };
    node*newnode(){
        pt->ch[0]=null;
        pt->ch[1]=null;
        pt->mx=0;
        pt->add=0;
        pt->v=0; 
        pt->s=1;
        pt->rev=0;  
        return pt++;
    }
    node*root;
    node x[maxn];
    void rotate(node*&o,int d)
    {
        node*k=o->ch[d^1];
        o->ch[d^1]=k->ch[d];
        k->ch[d]=o;
        o->maintain();k->maintain();
        o=k;
    }
    void splay(node*&o,int k)
    {   
        o->pushdown();
        int d=o->cmp(k);
        if(d==-1) return;
        if(d==1) k-=o->ch[0]->s+1;
        node*p=o->ch[d];
        p->pushdown();
        int d2=p->cmp(k);    
        int k2=d2?k-p->ch[0]->s-1:k;
        if(d2!=-1){
            splay(p->ch[d2],k2);
            d==d2?rotate(o,d^1):rotate(o->ch[d],d);
        }
        rotate(o,d^1);
    }
    node* build(int l,int r)
    {    
        if(l>=r) return null;
        int mid=(l+r)>>1;
        node*o=newnode();
        if(l<mid) o->ch[0]=build(l,mid);
        if(mid+1<r) o->ch[1]=build(mid+1,r);
        o->maintain();
        return o;
    }
    int read()
    {
        char c;    
        int f=1,ans=0;
        c=getchar();
        while(!isdigit(c)){
            if(c=='-') f=-1;
            c=getchar();
        }
        while(isdigit(c)){
            ans=ans*10+c-'0';
            c=getchar();
        }
        return f*ans;
    }
    void init()
    {
        pt=x;
        null=newnode();
        null->v=-inf;
        null->mx=-inf;
        null->s=0;
        root=build(0,n+2);
    } 
    int main()
    {
        n=read(),m=read();
        init();
        while(m--){
            int opt=read();
            if(opt==1){
                int l=read(),r=read(),delta=read();
                splay(root,l);
                splay(root->ch[1],r+1-root->ch[0]->s);
                root->ch[1]->ch[0]->add+=delta;
                root->ch[1]->ch[0]->v+=delta;
                root->ch[1]->ch[0]->mx+=delta;
            }else if(opt==2){
                int l=read(),r=read();
                if(l==r) continue;
                splay(root,l);
                splay(root->ch[1],r+1-root->ch[0]->s);
                root->ch[1]->ch[0]->rev^=1;
            }else{
                int l=read(),r=read();
                splay(root,l);
                splay(root->ch[1],r+1-root->ch[0]->s);
                printf("%d
    ",root->ch[1]->ch[0]->mx);
            }
        }
        return 0;
    }
    View Code

    1251: 序列终结者

    Time Limit: 20 Sec  Memory Limit: 162 MB
    Submit: 2791  Solved: 1110
    [Submit][Status][Discuss]

    Description

    网上有许多题,就是给定一个序列,要你支持几种操作:A、B、C、D。一看另一道题,又是一个序列 要支持几种操作:D、C、B、A。尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思。这道题目 就叫序列终结者吧。 【问题描述】 给定一个长度为N的序列,每个序列的元素是一个整数(废话)。要支持以下三种操作: 1. 将[L,R]这个区间内的所有数加上V。 2. 将[L,R]这个区间翻转,比如1 2 3 4变成4 3 2 1。 3. 求[L,R]这个区间中的最大值。 最开始所有元素都是0。

    Input

    第一行两个整数N,M。M为操作个数。 以下M行,每行最多四个整数,依次为K,L,R,V。K表示是第几种操作,如果不是第1种操作则K后面只有两个数。

    Output

    对于每个第3种操作,给出正确的回答。

    Sample Input

    4 4
    1 1 3 2
    1 2 4 -1
    2 1 3
    3 2 4

    Sample Output

    2
    【数据范围】
    N<=50000,M<=100000。

    HINT

     

    Source

    [Submit][Status][Discuss]
  • 相关阅读:
    HTML 样式表
    HTML笔记(框架)
    HTML笔记1
    SQL server 笔记9(备份还原触发器事务三范式)
    拦截器传参问题
    MethodFilterInterceptor(方法拦截器)配置excludeMethors
    js基础学习笔记(五)
    js基础学习笔记(四)
    笔记:CSS常用中文字体英文名称对照表
    推荐:掌握单页网站设计的5大技巧(转)
  • 原文地址:https://www.cnblogs.com/chensiang/p/4626734.html
Copyright © 2020-2023  润新知