zoukankan      html  css  js  c++  java
  • Bzoj1500 [NOI2005]维修数列

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 12469  Solved: 3955

    Description

    Input

    输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
    第2行包含N个数字,描述初始时的数列。
    以下M行,每行一条命令,格式参见问题描述中的表格。
    任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
    插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。

    Output

    对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。

    Sample Input

    9 8
    2 -6 3 5 1 -5 -3 6 3
    GET-SUM 5 4
    MAX-SUM
    INSERT 8 3 -5 7 2
    DELETE 12 1
    MAKE-SAME 3 3 2
    REVERSE 3 6
    GET-SUM 5 4
    MAX-SUM

    Sample Output

    -1
    10
    1
    10

    HINT

    Source

    Splay模板题

    真·一道题写一天

    每个指令都是基本操作,放在一起就迷之难写……

    由于空间限制,必须要重复使用del掉的旧结点

    几个WA点:

      申请新结点时,没有初始化ch[]

      序列st,ed编号记录错误,导致MAX-SUM操作转错

      pushdown只处理当前层,并把标记传给下层←会WA,非要把下一层也处理掉才行。

      pushdown没有判“当前结点为空时直接跳过”

      1 /*by SilverN*/
      2 #include<algorithm>
      3 #include<iostream>
      4 #include<cstring>
      5 #include<cstdio>
      6 #include<cmath>
      7 #include<vector>
      8 using namespace std;
      9 const int INF=1e9;
     10 const int mxn=1000100;
     11 int read(){
     12     int x=0,f=1;char ch=getchar();
     13     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     14     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     15     return x*f;
     16 }
     17 int stk[mxn],top;//回收结点 
     18 struct node{
     19     int ch[2];
     20     int fa,w,mk;
     21     int rx,lx,max;
     22     int size,sum;
     23     bool rev;
     24 }t[mxn];
     25 int a[mxn];//存储数值 
     26 int cnt=0;
     27 int root=0;
     28 int n,m,st,ed;
     29 void pd_cov(int rt){//区间修改
     30     if(!rt)return;
     31     t[rt].w=t[rt].mk;
     32     t[rt].sum=t[rt].size*t[rt].w;
     33     t[rt].lx=t[rt].rx=t[rt].max=max(t[rt].w,t[rt].sum);
     34     return;
     35 }
     36 void pd_rev(int rt){//区间翻转 
     37     if(!rt)return;
     38     t[rt].rev^=1;
     39     swap(t[rt].ch[0],t[rt].ch[1]);
     40     swap(t[rt].lx,t[rt].rx);//翻转左右连续和 
     41     return;
     42 }
     43 void pushdown(int x){
     44     if(!x)return;
     45     int lc=t[x].ch[0],rc=t[x].ch[1];
     46     if(t[x].mk!=-INF){
     47         t[lc].mk=t[rc].mk=t[x].mk;
     48         pd_cov(lc);pd_cov(rc);
     49         t[x].mk=-INF;
     50     }
     51     if(t[x].rev){
     52         pd_rev(lc);pd_rev(rc);
     53         t[x].rev=0;
     54     }
     55     return;
     56 }
     57 inline void pushup(int x){
     58     if(!x)return;
     59     int lc=t[x].ch[0],rc=t[x].ch[1];
     60     t[x].lx=max(t[lc].lx,t[lc].sum+t[x].w+max(0,t[rc].lx));
     61     t[x].rx=max(t[rc].rx,t[rc].sum+t[x].w+max(0,t[lc].rx));
     62     t[x].sum=t[lc].sum+t[x].w+t[rc].sum;
     63     t[x].max=max(max(t[lc].max,t[rc].max),max(t[rc].lx,0)+t[x].w+max(t[lc].rx,0));
     64     t[x].size=t[lc].size+t[rc].size+1;
     65     return;
     66 }
     67 void rotate(int x,int &k){
     68     int y=t[x].fa,z=t[y].fa,lc,rc;
     69     if(t[y].ch[0]==x)lc=0;else lc=1;
     70     rc=lc^1;
     71     if(y==k)k=x;
     72     else t[z].ch[t[z].ch[1]==y]=x;
     73     t[x].fa=z;t[y].fa=x;  t[t[x].ch[rc]].fa=y;
     74     t[y].ch[lc]=t[x].ch[rc];t[x].ch[rc]=y;
     75     pushup(y);
     76 }
     77 void relax(int x,int k){if(x!=k)relax(t[x].fa,k);pushdown(x);return;}
     78 void Splay(int x,int &k){
     79     relax(x,k);
     80     while(x!=k){
     81         int y=t[x].fa,z=t[y].fa;
     82         if(y!=k){
     83             if((t[z].ch[0]==y)^(t[y].ch[0]==x))rotate(x,k);
     84             else rotate(y,k);
     85         }
     86         rotate(x,k);
     87     }
     88     pushup(x);
     89     return;
     90 }
     91 inline void split(int x,int y){
     92     Splay(x,root);
     93     Splay(y,t[x].ch[1]);
     94     return;
     95 }
     96 inline int find(int x,int num){//查询序列中第num个数 
     97     pushdown(x);
     98     int lc=t[x].ch[0],rc=t[x].ch[1];
     99     if(t[lc].size>=num)return find(lc,num);
    100     if(t[lc].size+1==num)return x;
    101     return find(rc,num-t[lc].size-1);
    102 }
    103 inline int newnode(int x){//申请新结点 
    104     int rt;
    105     if(top)rt=stk[top--];else rt=++cnt;
    106     t[rt].w=a[x];
    107     t[rt].lx=t[rt].rx=t[rt].max=-INF;
    108     t[rt].rev=0;t[rt].mk=-INF;
    109     return rt;
    110 }
    111 int Build(int l,int r,int fa){
    112     if(l>r)return 0;
    113     int mid=(l+r)>>1,lc,rc;
    114     int x=newnode(mid);
    115     if(l<mid) t[x].ch[0]=Build(l,mid-1,x);
    116         else t[x].ch[0]=0;
    117     if(r>mid) t[x].ch[1]=Build(mid+1,r,x);
    118         else t[x].ch[1]=0;
    119     t[x].fa=fa;
    120     pushup(x);
    121     return x;
    122 }
    123 void del(int &x){
    124     if(!x)return;
    125     stk[++top]=x;
    126     t[x].fa=0;
    127     del(t[x].ch[0]),del(t[x].ch[1]);
    128     x=0;
    129     return;
    130 }
    131 void insert(int pos,int tot){
    132     for(int i=1;i<=tot;i++)a[i]=read();
    133     int tmp=Build(1,tot,0);
    134     int x=find(root,pos+1),y=find(root,pos+2);
    135     split(x,y);
    136     t[y].ch[0]=tmp;t[tmp].fa=y;
    137     pushup(y);pushup(x);
    138     return;
    139 }
    140 void msame(int pos,int tot,int c){
    141     int x=find(root,pos),y=find(root,pos+tot+1);
    142     split(x,y);
    143     t[t[y].ch[0]].mk=c;
    144     pd_cov(t[y].ch[0]);
    145     pushup(y);pushup(x);
    146     return;
    147 }
    148 void reverse(int pos,int tot){
    149     int x=find(root,pos),y=find(root,pos+tot+1);
    150     split(x,y);
    151     pd_rev(t[y].ch[0]);
    152     pushup(y);pushup(x);
    153     return;
    154 }
    155 void solvedel(int pos,int tot){
    156     int x=find(root,pos),y=find(root,pos+tot+1);
    157     split(x,y);
    158     del(t[y].ch[0]);
    159     pushup(y);pushup(x);
    160     return;
    161 }
    162 inline int getmax(int pos,int tot){
    163     split(st,ed);
    164     return t[t[ed].ch[0]].max;
    165 }
    166 inline int getsum(int pos,int tot){
    167     int x=find(root,pos),y=find(root,pos+tot+1);
    168     split(x,y);
    169     return t[t[y].ch[0]].sum;
    170 }
    171 void DEBUG(){
    172     printf("root:%d
    ",root);
    173     for(int i=1;i<=cnt;i++){
    174         printf("id:%d  fa:%d lc:%d rc:%d w:%d
    ",i,t[i].fa,t[i].ch[0],t[i].ch[1],t[i].w);
    175         printf("  lx:%d rx:%d mx:%d
    ",t[i].lx,t[i].rx,t[i].max);
    176         printf("  size:%d
    ",t[i].size);
    177     }
    178     return;
    179 }
    180 int main(){
    181     int i,j,x,y,c;
    182     n=read();m=read();
    183     for(i=1;i<=n;i++)a[i+1]=read();
    184     st=1;ed=n+2;
    185     a[st]=a[ed]=0;
    186     t[0].lx=t[0].rx=t[0].max=-INF;
    187     root=Build(1,n+2,0);
    188     st=find(root,st);ed=find(root,ed);//记录头尾结点的编号 
    189     char op[15];
    190     while(m--){
    191         scanf("%s",op);
    192         switch(op[0]){
    193             case 'I':x=read();y=read();insert(x,y);break;
    194             case 'D':{x=read();y=read();solvedel(x,y);break;}
    195             case 'M':{
    196                 if(op[2]=='K'){x=read();y=read();c=read();msame(x,y,c);}
    197                 else{printf("%d
    ",getmax(st,ed));}
    198                 break;
    199             }
    200             case 'R':{x=read();y=read();reverse(x,y);break;}
    201             case 'G':{x=read();y=read();printf("%d
    ",getsum(x,y));break;}
    202             case 'B':DEBUG();break;
    203         }
    204     }
    205     return 0;
    206 }
  • 相关阅读:
    vue 中引用echarts 初始化init undefind问题(Cannot read property ‘init‘ of undefined)
    粘性定位(position:sticky)实现固定表格表头、固定列
    js替换字符串中的空格,换行符 或 替换成<br>
    一个完整的大作业
    数据结构化与保存
    爬取所有校园新闻
    用requests库和BeautifulSoup4库爬取新闻列表
    中文词频统计及词云制作
    组合数据类型练习,英文词频统计实例
    字符串操作练习:星座、凯撒密码、99乘法表、词频统计预处理
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6229033.html
Copyright © 2011-2022 走看看