• bzoj 1500 [NOI 2005] 维修数列


    题目大意不多说了

    貌似每个苦逼的acmer都要做一下这个splay树的模版题目吧

    还是有很多操作的,估计够以后当模版了。。。。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <cmath>
      6 
      7 using namespace std;
      8 const int N = 1000010;
      9 const int INF = 0x3f3f3f3f;
     10 #define ls ch[x][0]
     11 #define rs ch[x][1]
     12 
     13 struct SplayTree{
     14     int ch[N][2] , pre[N];
     15     int ml[N] , mr[N] , mm[N]; //区间最大
     16     int val[N] , sz[N] , sum[N] , size , rt;
     17     int rev[N] , to[N]; // lazy标记
     18     int del[N] , top; //内部保存删除的数的位置,然后可以从其中提取位置给新进入的元素
     19     int a[N];
     20 
     21     void push_up(int x)
     22     {
     23         sz[x] = sz[ls]+sz[rs]+1;
     24         sum[x] = sum[ls]+sum[rs]+val[x];
     25         /*********************/
     26         ml[x] = max(ml[ls] , sum[ls]+val[x]+max(ml[rs] , 0));
     27         mr[x] = max(mr[rs] , sum[rs]+val[x]+max(mr[ls] , 0));
     28         mm[x] = max(mm[ls] , max(mm[rs] , max(ml[rs],0)+max(mr[ls],0)+val[x]));
     29         /*********************/
     30     }
     31 
     32     void push_down(int x)
     33     {
     34         if(rev[x]){
     35             if(ls){
     36                 rev[ls]^=1 ;
     37                 swap(ml[ls] , mr[ls]);
     38             }
     39             if(rs){
     40                 rev[rs]^=1 ;
     41                 swap(ml[rs] , mr[rs]);
     42             }
     43             swap(ls , rs);
     44             rev[x] = 0;
     45         }
     46         /**to[x]的初始化要注意**/
     47         if(to[x]!=-INF){
     48             if(ls){
     49                 sum[ls] = sz[ls]*to[x];
     50                 ml[ls] = mr[ls] = mm[ls] = max(sum[ls] , to[x]);
     51                 val[ls] = to[ls] = to[x];
     52             }
     53             if(rs){
     54                 sum[rs] = sz[rs]*to[x];
     55                 ml[rs] = mr[rs] = mm[rs] = max(sum[rs] , to[x]);
     56                 val[rs] = to[rs] = to[x];
     57             }
     58             to[x] = -INF;
     59         }
     60     }
     61 
     62     void newNode(int &x , int fa , int v)
     63     {
     64         if(top != -1)
     65             x = del[top--];
     66         else x = ++size;
     67         ch[x][0] = ch[x][1] = 0;
     68         pre[x] = fa;
     69         val[x] = v , sz[x] = 1;
     70         sum[x] = ml[x] = mr[x] = mm[x] = val[x];
     71         rev[x] = 0 , to[x] = -INF;
     72     }
     73 
     74     void build(int &x , int l , int r , int fa)
     75     {
     76         if(l>r) return;
     77         int m=(l+r)>>1;
     78         newNode(x , fa , a[m]);
     79         build(ls , l , m-1 , x);
     80         build(rs , m+1 , r , x);
     81         push_up(x);
     82     }
     83 
     84     void init(int n)
     85     {
     86         /*****因为所有点的最终叶子节点都下标设为了0,所以0上的数据要不影响整棵树*****/
     87         sz[0] = sum[0] = ch[0][0] = ch[0][1] = val[0] = pre[0] = 0;
     88         to[0] = ml[0] = mr[0] = mm[0] = -INF;
     89         rev[0] = 0;
     90         top = -1 , rt = size = 0;
     91         newNode(rt , 0 , -INF);
     92         newNode(ch[rt][1] , rt , -INF);
     93         build(ch[ch[rt][1]][0] , 1 , n , ch[rt][1]);
     94         push_up(ch[rt][1]);
     95         push_up(rt);
     96     }
     97 
     98     void Rotate(int x , int f)
     99     {
    100         int y=pre[x] , z=pre[y];
    101         /**y要旋转到下方,下传lazy标记**/
    102         push_down(y);
    103         ch[y][!f] = ch[x][f] , pre[ch[x][f]] = y;
    104         ch[x][f] = y , pre[y] = x;
    105         ch[z][ch[z][1]==y] = x , pre[x]=z;
    106         push_up(y);
    107         push_up(x);
    108     }
    109 
    110     void Splay(int x , int goal)
    111     {
    112         while(pre[x] != goal){
    113             if(pre[pre[x]] == goal) Rotate(x , ch[pre[x]][0]==x);
    114             else{
    115                 int y = pre[x] , z = pre[y];
    116                 int f = ch[z][0] == y;
    117                 if(ch[y][f] == x) Rotate(x , !f);
    118                 else Rotate(y,f);
    119                 Rotate(x , f);
    120             }
    121         }
    122         push_up(x);
    123         if(goal == 0) rt = x;
    124     }
    125 
    126     int Select(int pos)
    127     {
    128         int x = rt;
    129         push_down(x);
    130         while(sz[ls]+1 != pos){
    131             if(sz[ls]+1>pos) x=ls;
    132             else{
    133                 pos = pos-sz[ls]-1;
    134                 x = rs;
    135             }
    136             push_down(x);
    137         }
    138         return x;
    139     }
    140     /***从pos位置之后插入cnt个值***/
    141     void Insert(int pos , int cnt)
    142     {
    143         int x = Select(pos);
    144         Splay(x , 0);
    145         int y = Select(pos+1);
    146         Splay(y , x);
    147         build(ch[y][0] , 1 , cnt , y);
    148         /***这里build将a[1~cnt]插入到splay树中,要push_up更新***/
    149         push_up(y);
    150         push_up(x);
    151     }
    152     /***回收被删除的数的位置***/
    153     void Recycle(int x)
    154     {
    155         if(x){
    156             del[++top]=x;
    157             Recycle(ls);
    158             Recycle(rs);
    159         }
    160     }
    161 
    162     void Delete(int s , int t)
    163     {
    164         int x = Select(s-1) , y = Select(t+1);
    165         Splay(x , 0) , Splay(y , x);
    166         Recycle(ch[y][0]);
    167         ch[y][0] = 0;
    168         /***这里y的左子树删除,明显子树数据改变,所以要重新push_up更新数据***/
    169         push_up(y);
    170         push_up(x);
    171     }
    172     /****将s~t区间内的所有值都修改为v****/
    173     void update(int s , int t , int v)
    174     {
    175         int x = Select(s-1) , y = Select(t+1);
    176         Splay(x , 0) , Splay(y , x);
    177         int ptr = ch[y][0];
    178         to[ptr]=v;
    179         val[ptr]=v;
    180         sum[ptr]=v*sz[ptr];
    181         ml[ptr] = mr[ptr] = mm[ptr] = max(sum[ptr] , v);
    182         return ;
    183     }
    184 
    185     void Reverse(int s , int t)
    186     {
    187         int x = Select(s-1) , y = Select(t+1);
    188         Splay(x , 0) , Splay(y , x);
    189         int ptr = ch[y][0];
    190         rev[ptr]^=1;
    191         swap(ml[ptr] , mr[ptr]);
    192     }
    193 
    194     int querySum(int s , int t)
    195     {
    196         int x = Select(s-1) , y =  Select(t+1);
    197        // cout<<"x: "<<x<<" y: "<<y<<endl;
    198         Splay(x , 0) , Splay(y , x);
    199         return sum[ch[y][0]];
    200     }
    201 
    202     int queryMax()
    203     {
    204         int x = Select(1) , y = Select(sz[rt]);
    205         Splay(x , 0) , Splay(y , x);
    206         return mm[ch[y][0]];
    207     }
    208 }spt;
    209 int main()
    210 {
    211   //  freopen("a.in" , "r" , stdin);
    212     int n , m;
    213     char str[20] ;
    214     int s , t , v , pos , k;
    215     while(~scanf("%d%d" , &n , &m))
    216     {
    217         for(int i=1 ; i<=n ; i++) scanf("%d" , &spt.a[i]);
    218         spt.init(n);
    219         /*
    220         for(int i=0 ; i<=spt.size ; i++){
    221             cout<<"i: "<<i<<" sum: "<<spt.sum[i]<<" l: "<<spt.ch[i][0]<<" lv: "<<spt.val[spt.ch[i][0]]<<" r: "<<spt.ch[i][1]<<" rv: "<<spt.val[spt.ch[i][1]]<<endl;
    222         }*/
    223         for(int i=0 ; i<m ; i++){
    224             scanf("%s" , str);
    225             if(str[0] == 'I'){
    226                 scanf("%d%d" , &pos , &k);
    227                 for(int i=1 ; i<=k ; i++) scanf("%d" , &spt.a[i]);
    228                 spt.Insert(pos+1 , k);
    229             }
    230             else if(str[0]=='D'){
    231                 scanf("%d%d" , &pos , &k);
    232                 spt.Delete(pos+1 , pos+k);
    233             }
    234             else if(str[0] == 'M' && str[2] == 'K'){
    235                 scanf("%d%d%d" , &pos , &k , &v);
    236                 spt.update(pos+1 , pos+k , v);
    237             }
    238             else if(str[0] == 'R'){
    239                 scanf("%d%d" , &pos , &k);
    240                 spt.Reverse(pos+1 , pos+k);
    241             }
    242             else if(str[0] == 'G'){
    243                 scanf("%d%d" , &pos , &k);
    244                 printf("%d
    " , spt.querySum(pos+1 , pos+k));
    245             }
    246             else{
    247                 /****这里不能直接用spt.mm[rt]作为答案,因为为了方便查询,
    248                 我们增加了两个不包含在本身数组的点,直接spt.mm[rt]会把这两个点也算进来***/
    249                 printf("%d
    " , spt.queryMax());
    250             }
    251         }
    252     }
    253     return 0;
    254 }
  • 相关阅读:
    电磁学10.安培环路定律
    电磁学9.毕奥-萨法尔定律与高斯磁定理
    电磁学8.磁场中的运动电荷
    C语言-指针
    Windows和Linux的简单对比
    电磁学7.磁场与洛伦兹力
    睡眠呼吸机-呼吸触发相关算法
    电磁学6.电流与电动势
    code的用法
    字符串处理
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4446054.html
Copyright © 2020-2023  润新知