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

    题目大意:维护一种数据结构,支持下列操作:

    1.将一个区间加上一个数

    2.将一个区间翻转

    3.询问一段区间的最大值

    感受:傻叉题还敢说自己是序列终结者O__O "…

    这道题写的时候还没修改我的splay模板,所以常数较大。。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int read(){
     4   int x=0,f=1;char ch=getchar();
     5   while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     6   while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     7   return x*f;
     8 }
     9 #define N 50005
    10 int n,m,root,v[N],fa[N],sz[N],mx[N],tag[N],rev[N],ch[N][2];
    11 inline void pushup(int k){
    12   int l=ch[k][0],r=ch[k][1];
    13   mx[k]=max(mx[l],mx[r]);
    14   mx[k]=max(mx[k],v[k]);
    15   sz[k]=sz[l]+sz[r]+1;
    16 }
    17 void pushdown(int k){
    18   int l=ch[k][0],r=ch[k][1],t=tag[k];
    19   if(t){
    20     tag[k]=0;
    21     if(l){tag[l]+=t;mx[l]+=t;v[l]+=t;}
    22     if(r){tag[r]+=t;mx[r]+=t;v[r]+=t;}
    23   }
    24   if(rev[k]){
    25     rev[k]=0;
    26     rev[l]^=1;rev[r]^=1;
    27     swap(ch[k][0],ch[k][1]);
    28   }
    29 }
    30 void Pushdown(int x){
    31   if(fa[x])Pushdown(fa[x]);
    32   pushdown(x);
    33 }
    34 void rotate(int x,int &beto){
    35   int y=fa[x],t=ch[y][1]==x;
    36   if(y!=beto)ch[fa[y]][ch[fa[y]][1]==y]=x;else beto=x;
    37   fa[x]=fa[y];fa[y]=x;
    38   fa[ch[x][!t]]=y;
    39   ch[y][t]=ch[x][!t];
    40   ch[x][!t]=y;
    41   pushup(y);pushup(x);
    42 }
    43 void splay(int x,int &beto){
    44   Pushdown(x);
    45   while(x!=beto){
    46     int y=fa[x];
    47     if(y!=beto){
    48       if((ch[fa[y]][1]==y)==(ch[y][1]==x))rotate(y,beto);
    49       else rotate(x,beto);
    50     }rotate(x,beto);
    51   }
    52 }
    53 void build(int l,int r,int f){
    54   int mid=l+r>>1;
    55   fa[mid]=f;sz[mid]=1;
    56   if(mid<f)ch[f][0]=mid;else ch[f][1]=mid;
    57   if(l==r)return;
    58   if(l<mid)build(l,mid-1,mid);
    59   if(r>mid)build(mid+1,r,mid);
    60   pushup(mid);
    61 }
    62 int find_k(int x,int k){
    63   pushdown(x);
    64   if(sz[ch[x][0]]==k-1)return x;
    65   if(sz[ch[x][0]]<k-1)return find_k(ch[x][1],k-sz[ch[x][0]]-1);
    66   return find_k(ch[x][0],k);
    67 }
    68 int main(){
    69   n=read();m=read();n+=2;
    70   mx[0]=-1e9;
    71   build(1,n,0);root=(1+n)>>1;
    72   for(int i=1;i<=m;i++){
    73     int t=read(),l=read(),r=read();r+=2;
    74     l=find_k(root,l);r=find_k(root,r);
    75     splay(l,root);splay(r,ch[l][1]);
    76     int z=ch[r][0];
    77     if(t==1){
    78       int x=read();
    79       tag[z]+=x;v[z]+=x;mx[z]+=x;
    80     }
    81     if(t==2)rev[z]^=1;
    82     if(t==3)printf("%d
    ",mx[z]);
    83   }
    84   return 0;
    85 }
    86 
    View Code

    1251: 序列终结者

    Time Limit: 20 Sec  Memory Limit: 162 MB
    Submit: 3557  Solved: 1484
    [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。
  • 相关阅读:
    web性能优化
    9.1_the end
    8.28_the end
    1.获取元素绝对位置
    8.14_end
    JavaScript 函数用途
    JavaScirpt事件处理
    《JavaScript语言精粹》读书笔记
    《图解http协议》之HTTPs学习笔记
    Laya 1.x 按文件夹TS代码合并
  • 原文地址:https://www.cnblogs.com/wjyi/p/5612143.html
Copyright © 2011-2022 走看看