zoukankan      html  css  js  c++  java
  • [bzoj1500 维修数列](NOI2005) (splay)

    真的是太弱了TAT。。。光是把代码码出来就花了3h。。还调了快1h才弄完T_T

    号称考你会不会splay(当然通过条件是1h内AC。。吓傻)。。。

    黄学长的题解:http://hzwer.com/2841.html 

    当然了蒟蒻的splay模板全部都是借(抄)鉴(袭)黄学长的。。。。

    主要是注意任何对子树的修改一定要记得pushup一定要记得pushup一定要记得pushup。。。计算最大子段和和bzoj1858一个姿势,就是维护子树的最大子段和,从左和从右开始的最大子段和(当然了平衡树和线段树在这里还是有点区别的);

    对于修改和翻转可以打懒标记。。。插入的话可以先把要插入的数建出一颗splay树,然后把新树和原来的树连起来;

    为了避免判断区间边界啊什么的可以多建两个边界节点。。。

    据说要加上垃圾回收,这样的话还要新开一个id数组用来存节点的编号,那样的话数组开到50w就可以了。。

    如果不要垃圾回收的话,删除时把对应区间的子树与原来的树断开连接就好了,垃圾回收还得把要砍掉的子树里面的节点遍历重置。。。oj上没写数据范围让人感觉有点虚。。

      1 #include<stdio.h>
      2 #include<math.h>
      3 #include<queue>
      4 #include<iostream>
      5 #include<algorithm>
      6 using namespace std;
      7 const int inf=1002333333;
      8 const int maxn=500233;//题目又没说数据范围= =//经测试加了垃圾优化开50w就好了= = 
      9 struct zs{
     10     int c[2],fa,mx,lmx,rmx,val,size,sum;
     11     bool change,rev; 
     12 }tree[maxn];
     13 queue<int>q;
     14 int a[maxn],id[maxn];
     15 char iid[23];
     16 int i,j,k,n,m,cnt,tot,x,c,root;
     17 void update(int now){
     18     int l=tree[now].c[0],r=tree[now].c[1];
     19     tree[now].size=tree[l].size+tree[r].size+1;
     20     tree[now].sum=tree[l].sum+tree[r].sum+tree[now].val;
     21     tree[now].mx=max(tree[l].mx,tree[r].mx);
     22     tree[now].mx=max(tree[now].mx,tree[l].rmx+tree[now].val+tree[r].lmx);
     23     tree[now].lmx=max(tree[l].lmx,tree[l].sum+tree[now].val+tree[r].lmx);
     24     tree[now].rmx=max(tree[r].rmx,tree[r].sum+tree[now].val+tree[l].rmx);
     25 }
     26 void deal(int now,bool change,bool rev,int val){
     27     if(change){
     28         tree[now].change=1;
     29         tree[now].val=val;
     30         tree[now].sum=tree[now].size*val;
     31         if(val>0)
     32             tree[now].mx=tree[now].lmx=tree[now].rmx=tree[now].sum;
     33         else tree[now].mx=val,tree[now].lmx=tree[now].rmx=0;
     34     }
     35     else//如果整段覆盖了翻不翻转都一样 
     36     if(rev){
     37         tree[now].rev^=1;
     38 //        printf("!    %d %d %d
    ",now,tree[now].c[0],tree[now].c[1]);
     39         swap(tree[now].c[0],tree[now].c[1]);
     40         swap(tree[now].lmx,tree[now].rmx);
     41     }
     42 }
     43 void pushdown(int now){
     44     int l=tree[now].c[0],r=tree[now].c[1];
     45     if(l)deal(l,tree[now].change,tree[now].rev,tree[now].val);
     46     if(r)deal(r,tree[now].change,tree[now].rev,tree[now].val);
     47     tree[now].change=tree[now].rev=0;
     48 }
     49 void build(int l,int r,int premid){
     50     int now,mid,fa;
     51     if(l>r)return;
     52     mid=(l+r)>>1;
     53     fa=id[premid];now=id[mid];//本来id[i]==i,但因为垃圾回收。。。 
     54     if(mid<premid)tree[fa].c[0]=now;else tree[fa].c[1]=now;
     55     tree[now].fa=fa;
     56     tree[now].val=a[mid];
     57     if(l<r){
     58         build(l,mid-1,mid);build(mid+1,r,mid);
     59         update(now);
     60     }else{
     61 //        printf("  !%d %d
    ",now,tree[now].val);
     62         tree[now].size=1;
     63         tree[now].mx=tree[now].sum=tree[now].val;
     64         if(tree[now].val>0)tree[now].lmx=tree[now].rmx=tree[now].mx;
     65         else tree[now].lmx=tree[now].rmx=0;
     66     }
     67 //    printf("!   %d %d %d %d %d %d %d %d
    ",now,tree[now].c[0],tree[now].c[1],tree[now].mx,tree[now].lmx,tree[now].rmx,tree[now].change,tree[now].rev);
     68 }
     69 void rotate(int now,int&root){
     70     int fa,gfa,l,r;
     71     fa=tree[now].fa;gfa=tree[fa].fa;
     72     if(fa==root)root=now;
     73     else tree[gfa].c[tree[gfa].c[0]!=fa]=now;
     74     if(tree[fa].c[0]==now)l=0;else l=1;
     75     r=l^1;
     76     tree[now].fa=gfa;tree[fa].fa=now;
     77     tree[fa].c[l]=tree[now].c[r];tree[now].c[r]=fa;
     78     tree[tree[fa].c[l]].fa=fa;
     79     update(fa);update(now);
     80 }
     81 void splay(int now,int&root){
     82     int fa,gfa;
     83     while(now!=root){
     84         fa=tree[now].fa;gfa=tree[fa].fa;
     85         if(fa!=root)
     86             if((tree[fa].c[0]==now)^(tree[gfa].c[0]==fa))rotate(now,root);
     87             else rotate(fa,root);
     88         rotate(now,root);
     89     }
     90 }
     91 int find(int now,int k){
     92     if(tree[now].change||tree[now].rev)pushdown(now);
     93     int l=tree[now].c[0];
     94     if(k<=tree[l].size)return find(l,k);
     95     else if(k==tree[l].size+1)return now;
     96     else return find(tree[now].c[1],k-tree[l].size-1);
     97 }
     98 void ins(int pos,int tot){
     99 //    int now=find(root,pos+1);
    100     for(int i=1;i<=tot;i++)scanf("%d",&a[i]);
    101     for(int i=1;i<=tot;i++)
    102         if(!q.empty())id[i]=q.front(),q.pop();
    103         else id[i]=++cnt;
    104     int troot=id[(tot+1)>>1];
    105     build(1,tot,0);
    106     int x=find(root,pos+1),y=find(root,pos+2);
    107     splay(x,root);splay(y,tree[x].c[1]);
    108     tree[y].c[0]=troot;tree[troot].fa=y;
    109     update(y);update(x);
    110 //    printf("   !%d
    ",root);
    111 }
    112 void recover(int &now){
    113     tree[now].fa=0;
    114     if(tree[now].c[0])recover(tree[now].c[0]);
    115     if(tree[now].c[1])recover(tree[now].c[1]);
    116     q.push(now);
    117     tree[now].change=tree[now].rev=0; 
    118     now=0;
    119 }
    120 void del(int pos,int tot){
    121 //    int now=find(root,pos+1);
    122     int x=find(root,pos),y=find(root,pos+tot+1);
    123     splay(x,root);splay(y,tree[x].c[1]);
    124 //    int z=tree[y].c[0];tree[y].c[0]=0;
    125     recover(tree[y].c[0]);
    126     update(y);update(x);//要更新祖先TAT 
    127 }
    128 void bilibili(int pos,int tot,int change,int rev,int val){//处理修改&&翻转 
    129     int x=find(root,pos),y=find(root,pos+tot+1);
    130     splay(x,root);splay(y,tree[x].c[1]);
    131 //    printf("   !  %d %d %d %d
    ",tree[y].c[0],change,rev,val);
    132     deal(tree[y].c[0],change,rev,val);
    133     update(y);update(x);//也要更新祖先TAT 
    134 //    printf("!  %d %d
    ",y,x);
    135 }
    136 void getsum(int pos,int tot){
    137 //    int now=find(root,pos+1);
    138     int x=find(root,pos),y=find(root,pos+tot+1);
    139     splay(x,root);splay(y,tree[x].c[1]);
    140     int z=tree[y].c[0];
    141     printf("%d
    ",tree[z].sum);
    142 }
    143 int main(){
    144     scanf("%d%d",&n,&m);
    145     for(i=1;i<=n;i++)scanf("%d",&a[i+1]);
    146     a[1]=a[n+2]=-inf;
    147     for(i=1;i<=n+2;i++)id[i]=i;
    148     tree[0].mx=-inf;
    149     root=(n+2+1)>>1;cnt=n+2;
    150     build(1,n+2,0);
    151 //    for(i=1;i<=cnt;i++)printf("    %d %d %d %d %d %d
    ",i,tree[i].c[0],tree[i].c[1],tree[i].mx,tree[i].lmx,tree[i].rmx);
    152     for(i=1;i<=m;i++){
    153         scanf("%s",iid);
    154         if(iid[2]=='S')scanf("%d%d",&x,&tot),ins(x,tot);
    155         else if(iid[2]=='L')scanf("%d%d",&x,&tot),del(x,tot);
    156         else if(iid[2]=='K')scanf("%d%d%d",&x,&tot,&c),bilibili(x,tot,1,0,c); 
    157         else if(iid[2]=='V')scanf("%d%d",&x,&tot),bilibili(x,tot,0,1,0);
    158         else if(iid[2]=='T')scanf("%d%d",&x,&tot),getsum(x,tot);
    159         else if(iid[2]=='X')printf("%d
    ",tree[root].mx);
    160         //if(i==4)
    161 //        for(int i=1;i<=cnt;i++)printf("    %d %d %d %d %d %d %d %d
    ",i,tree[i].c[0],tree[i].c[1],tree[i].mx,tree[i].lmx,tree[i].rmx,tree[i].change,tree[i].rev);
    162   //      return 233;
    163     }
    164     return 0;
    165 }
    View Code

    //连续几天写到的题目都没有数据范围是什么鬼。。。

    //至于读入的时候少打一个%d这种错显然只有傻叉才会犯的啊TAT

    //变量名太长的悲剧。。。把几个过程缩成一个结果代码量还是别人的两倍T_T

    感觉自己还不会splay。。。果然是太弱了。。也许过一阵子再来写这题效果会好点= =

    2015.8.1:4h

    2015.8.6:2h : 注意删点的时候那些新建节点时没有初始化的信息都要初始化,

    2016.1.6:4h+。。TAT。。太久没玩懒标记结果卡了一晚上+一节电脑课。。。要好好想一下什么时候更新本节点的信息。。

  • 相关阅读:
    Reborn
    个人总结
    第十六周个人进度条
    梦断代码阅读笔记03
    第十五周个人进度条
    第十四周个人进度条
    第十三周个人进度条
    冲刺9
    冲刺8
    事后诸葛亮会议
  • 原文地址:https://www.cnblogs.com/czllgzmzl/p/4694734.html
Copyright © 2011-2022 走看看