• CODEVS 4655 序列终结者-splay(区间更新、区间翻转、区间最值)


    4655 序列终结者

     

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 大师 Master
     
     
     
    题目描述 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 Description

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

    输出描述 Output Description

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

    样例输入 Sample Input

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

    样例输出 Sample Output

    2

    数据范围及提示 Data Size & Hint

    N<=50000,M<=100000。

    题意中文。

    直接以前的题目改一下就可以。

    翻转不需要pushup,因为建树的时候已经算过了,再算一次就不对了。更新也不需要pushup,因为加值不影响size。

    没脑子的我简直想暴打自己一顿,调了快1个小时bug,怎么也过不了,最后发现是查询3操作,query(l,r),写成query(1,n),简直要死。

    mdzz,浪费了一个小时。

    代码:

      1 //splay
      2 #include<bits/stdc++.h>
      3 using namespace std;
      4 typedef long long ll;
      5 const int maxn=1e5+10;
      6 const int inf=0x3f3f3f3f;
      7 
      8 int root;
      9 int tree[maxn][2],fa[maxn],id[maxn];
     10 int sz[maxn],val[maxn],Max[maxn];
     11 int add[maxn],rev[maxn];
     12 
     13 void pushup(int x)
     14 {
     15     int l=tree[x][0],r=tree[x][1];
     16     Max[x]=max(max(Max[l],Max[r]),val[x]);
     17     sz[x]=sz[l]+sz[r]+1;
     18 }
     19 
     20 void pushdown(int x)
     21 {
     22     int l=tree[x][0],r=tree[x][1];
     23     if(add[x]){
     24         if(l) val[l]+=add[x],Max[l]+=add[x],add[l]+=add[x];
     25         if(r) val[r]+=add[x],Max[r]+=add[x],add[r]+=add[x];
     26         add[x]=0;
     27     }
     28     if(rev[x]){
     29         rev[x]=0;rev[l]^=1;rev[r]^=1;
     30         swap(tree[x][0],tree[x][1]);
     31     }
     32 }
     33 
     34 void rotate(int x,int &k)
     35 {
     36     int y=fa[x],z=fa[y],l=(tree[y][1]==x),r=l^1;
     37     if(y==k) k=x;
     38     else tree[z][tree[z][1]==y]=x;
     39     fa[tree[x][r]]=y;fa[y]=x;fa[x]=z;
     40     tree[y][l]=tree[x][r];tree[x][r]=y;
     41     pushup(y);pushup(x);
     42 }
     43 
     44 void splay(int x,int &k)
     45 {
     46     while(x!=k){
     47         int y=fa[x],z=fa[y];
     48         if(y!=k){
     49             if((tree[z][0]==y)^(tree[y][0]==x)) rotate(x,k);
     50             else rotate(y,k);
     51         }
     52         rotate(x,k);
     53     }
     54 }
     55 
     56 int find(int x,int rk)
     57 {
     58     if(add[x]||rev[x]) pushdown(x);
     59     int l=tree[x][0],r=tree[x][1];
     60     if(sz[l]+1==rk) return x;
     61     else if(sz[l]>=rk) return find(l,rk);
     62     else return find(r,rk-sz[l]-1);
     63 }
     64 
     65 int split(int l,int r)
     66 {
     67     int x=find(root,l),y=find(root,r+2);
     68     splay(x,root);splay(y,tree[x][1]);
     69     return tree[y][0];
     70 }
     71 
     72 void rever(int l,int r)
     73 {
     74     int x=split(l,r),y=fa[x];
     75     rev[x]^=1;
     76 //    swap(tree[x][0],tree[x][1]);
     77 //    pushup(y);pushup(fa[y]);
     78 }
     79 
     80 void update(int l,int r,int v)
     81 {
     82     int x=split(l,r),y=fa[x];
     83     val[x]+=v;Max[x]+=v;add[x]+=v;
     84 //    pushup(y);pushup(fa[y]);
     85 }
     86 
     87 int find_max(int l,int r)
     88 {
     89     int x=split(l,r);
     90     return Max[x];
     91 }
     92 
     93 void build(int l,int r,int f)
     94 {
     95     if(l>r) return ;
     96     if(l==r){
     97         fa[l]=f;
     98         sz[l]=1;
     99         val[l]=0;
    100         tree[f][l>=f]=l;
    101         return ;
    102     }
    103 
    104     int m=(l+r)>>1;
    105     build(l,m-1,m);
    106     build(m+1,r,m);
    107     fa[m]=f;
    108     pushup(m);
    109     tree[f][m>=f]=m;
    110 }
    111 
    112 int main()
    113 {
    114     int n,m;
    115     scanf("%d%d",&n,&m);
    116 //    for(int i=1;i<=n+2;i++){
    117 //        id[i]=i;
    118 //    }
    119     Max[0]=-inf;
    120     build(1,n+2,0);
    121     root=(n+3)>>1;
    122     for(int i=1;i<=m;i++){
    123         int op;
    124         scanf("%d",&op);
    125         if(op==1){
    126             int l,r,v;
    127             scanf("%d%d%d",&l,&r,&v);
    128             update(l,r,v);
    129         }
    130         else if(op==2){
    131             int l,r;
    132             scanf("%d%d",&l,&r);
    133             rever(l,r);
    134         }
    135         else if(op==3){
    136             int l,r;
    137             scanf("%d%d",&l,&r);
    138             int maxx=find_max(l,r);
    139             printf("%d
    ",maxx);
    140         }
    141     }
    142     return 0;
    143 }

    滚了。

  • 相关阅读:
    安装Mariadb10.6.10 需要升级CMake 3.0 以上版本
    zabbix 安装
    ubuntu常用的命令介绍
    关于关闭UAC的注册表设置,EnableLUA不能设置为0
    ubuntu通过MobaXterm或者xshell连接更换源
    公钥私钥帐号绑定ssh登录
    excel提示内存或磁盘空间不足怎么办
    Windows的环境变量
    知乎禁止复制申请转载怎么办
    右击菜单增加IobitUnlocker解锁
  • 原文地址:https://www.cnblogs.com/ZERO-/p/10746670.html
Copyright © 2020-2023  润新知