zoukankan      html  css  js  c++  java
  • BZOJ 1251: 序列终结者

    1251: 序列终结者

    Time Limit: 20 Sec  Memory Limit: 162 MB
    Submit: 3773  Solved: 1579
    [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

    splay处理。

    #include<cstdio>
    #include<iostream>
    #define IN inline
    #define R register
    using namespace std;
    const int N=1e5+10;
    int n,m,rt,siz[N],fa[N],c[N][2];
    bool rev[N];
    int tag[N],mx[N],w[N];
    IN int read(){
        R int x=0;R bool f=1;
        R char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=0;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    IN void updata(int k){
        int l=c[k][0],r=c[k][1];
        siz[k]=siz[l]+siz[r]+1;
        mx[k]=max(mx[l],mx[r]);
        mx[k]=max(mx[k],w[k]);
    }
    IN void pushdown(int k){
        int &l=c[k][0],&r=c[k][1];
        if(tag[k]){
            if(l) tag[l]+=tag[k],mx[l]+=tag[k],w[l]+=tag[k];
            if(r) tag[r]+=tag[k],mx[r]+=tag[k],w[r]+=tag[k];
            tag[k]=0;
        }
        if(rev[k]){
            swap(l,r);
            rev[l]^=1;rev[r]^=1;
            rev[k]=0;
        }
    }
    IN void rotate(int x,int &k){
        int y=fa[x],z=fa[y],l,r;
        l=(c[y][1]==x);r=l^1;
        if(y==k) k=x;
        else c[z][c[z][1]==y]=x;
        fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
        c[y][l]=c[x][r];c[x][r]=y;
        updata(y);updata(x);
    }
    IN void splay(int x,int &k){
        while(x!=k){
            int y=fa[x],z=fa[y];
            if(y!=k){
                if((c[z][0]==y)^(c[y][0]==x)) rotate(x,k);
                else rotate(y,k); 
            }
            rotate(x,k);
        }
    }
    void build(int l,int r,int f){
        if(l>r) return ;
        int mid=l+r>>1; 
        c[f][mid>=f]=mid;
        siz[mid]=1;fa[mid]=f;
        if(l==r) return ;
        build(l,mid-1,mid);build(mid+1,r,mid);
        updata(mid);
    }
    int find(int k,int rk){
        pushdown(k);
        int l=c[k][0],r=c[k][1];
        if(siz[l]+1==rk) return k;
        return siz[l]>=rk?find(l,rk):find(r,rk-siz[l]-1);
    }
    IN void add(int l,int r,int v){
        int x=find(rt,l),y=find(rt,r+2);
        splay(x,rt);splay(y,c[x][1]);
        int &z=c[y][0];
        tag[z]+=v;mx[z]+=v;w[z]+=v;
    }
    IN void rever(int l,int r){
        int x=find(rt,l),y=find(rt,r+2);
        splay(x,rt);splay(y,c[x][1]);
        rev[c[y][0]]^=1;
    }
    IN int qmax(int l,int r){
        int x=find(rt,l),y=find(rt,r+2);
        splay(x,rt);splay(y,c[x][1]);
        return mx[c[y][0]];
    }
    int main(){
        mx[0]=-0x7fffffff;//注意这里有负数,所以mx[0]要定义最小值
        n=read();m=read();
        build(1,n+2,0);rt=n+3>>1;
        for(int i=0,opt,l,r,v;i<m;i++){
            opt=read();l=read();r=read();
            switch(opt){
                case 1:v=read();add(l,r,v);break;
                case 2:rever(l,r);break;
                case 3:printf("%d
    ",qmax(l,r));break;
            }
        }
        return 0;
    }

     

  • 相关阅读:
    Single Number II
    Pascal's Triangle
    Remove Duplicates from Sorted Array
    Populating Next Right Pointers in Each Node
    Minimum Depth of Binary Tree
    Unique Paths
    Sort Colors
    Swap Nodes in Pairs
    Merge Two Sorted Lists
    Climbing Stairs
  • 原文地址:https://www.cnblogs.com/shenben/p/6195262.html
Copyright © 2011-2022 走看看