zoukankan      html  css  js  c++  java
  • 数据结构(Splay平衡树):COGS 339. [NOI2005] 维护数列

    时间限制:3 s   内存限制:256 MB

     

    【问题描述】

    请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格)

    操作编号

    输入文件中的格式

    说明


    1.  插入



    INSERT_posi_tot_c1_c2_..._ctot

    在当前数列的第 posi 个数字后插入 tot

    个数字:c1, c2, …, ctot;若在数列首插

    入,则 posi 为 0

    2.  删除


    DELETE_posi_tot

    从当前数列的第 posi 个数字开始连续

    删除 tot 个数字

    3.  修改


    MAKE-SAME_posi_tot_c

    将当前数列的第 posi 个数字开始的连

    续 tot 个数字统一修改为 c

    4.  翻转


    REVERSE_posi_tot

    取出从当前数列的第 posi 个数字开始

    的 tot 个数字,翻转后放入原来的位置

    5.  求和


    GET-SUM_posi_tot

    计算从当前数列开始的第 posi 个数字

    开始的 tot 个数字的和并输出

    6.  求和最

    大的子列


    MAX-SUM

    求出当前数列中和最大的一段子列,

    并输出最大和

    【输入格式】

    输入文件的第 1 行包含两个数 N 和 M,N 表示初始时数列中数的个数,M表示要进行的操作数目。

    第 2 行包含 N 个数字,描述初始时的数列。

    以下 M 行,每行一条命令,格式参见问题描述中的表格。

    【输出格式】

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

    【输入样例】

    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
    

    【输出样例】

    -1
    10
    1
    10
    

    【样例说明】

    初始时,我们拥有数列 2 -6 3 5 1 -5 -3 6 3

    执行操作 GET-SUM 5 4,表示求出数列中从第 5 个数开始连续 4 个数字之和,1+(-5)+(-3)+6 = -1:

    2     -6     3      5      1     -5    -3     6      3
    
    

    执行操作 MAX-SUM,表示要求求出当前数列中最大的一段和,应为 3+5+1+(-5)+(-3)+6+3 = 10:

    2     -6     3      5      1     -5    -3     6      3
    
    

    执行操作 INSERT 8 3 -5 7 2,即在数列中第 8 个数字后插入-5 7 2,

    2     -6     3      5      1     -5    -3     6     -5     7      2      3
    
    

    执行操作 DELETE 12 1,表示删除第 12 个数字,即最后一个:

    2     -6     3      5      1     -5    -3     6     -5     7      2
    
    

    执行操作 MAKE-SAME 3 3 2,表示从第 3 个数开始的 3 个数字,统一修改为 2:

    2	-6	3	5	1	-5	-3	6	-5	7	2
    

    改为

    2	-6	2	2	2	-5	-3	6	-5	7	2
    

    执行操作 REVERSE 3 6,表示取出数列中从第 3 个数开始的连续 6 个数:

    2           -6            2             2             2           -5            -3            6            -5            7            2
    

    如上所示的灰色部分 2 2 2 -5 -3 6,翻转后得到 6 -3 -5 2 2 2,并放回原来位置:

    2     -6     6     -3     -5     2      2      2     -5     7      2
    

    最后执行 GET-SUM 5 4 和 MAX-SUM,不难得到答案 1 和 10。

    2            -6            6            -3            -5           2             2            2             -5           7             2
    

    【评分方法】

    本题设有部分分,对于每一个测试点:

    • 如果你的程序能在输出文件正确的位置上打印 GET-SUM 操作的答案,你可以得到该测试点 60%的分数;
    • 如果你的程序能在输出文件正确的位置上打印 MAX-SUM 操作的答案,你可以得到该测试点 40%的分数;
    • 以上两条的分数可以叠加,即如果你的程序正确输出所有 GET-SUM 和MAX-SUM 操作的答案,你可以得到该测试点 100%的分数。

    请注意:如果你的程序只能正确处理某一种操作,请确定在输出文件正确的位置上打印结果,即必须为另一种操作留下对应的行,否则我们不保证可以正确评分。

    【数据规模和约定】

     

    • 你可以认为在任何时刻,数列中至少有 1 个数。
    • 输入数据一定是正确的,即指定位置的数在数列中一定存在。

     

    • 50%的数据中,任何时刻数列中最多含有 30 000 个数;
    • 100%的数据中,任何时刻数列中最多含有 500 000 个数。

     

    • 100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。
    • 100%的数据中,M ≤20 000,插入的数字总数不超过 4 000 000 个,输入文件大小不超过 20MBytes。

     

      这道题需要注意细节,写之前请理清思路!!!

     

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 using namespace std;
      5 const int maxn=5000010;
      6 const int INF=1000000000;
      7 int fa[maxn],ch[maxn][2],sz[maxn],key[maxn];
      8 int mark[maxn],flip[maxn],sum[maxn],n,Q;
      9 int lx[maxn],rx[maxn],mx[maxn],rt,cnt;
     10 char s[15];
     11 void Push_up(int x){
     12     sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
     13     sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+key[x];
     14     lx[x]=max(lx[ch[x][0]],key[x]+sum[ch[x][0]]+lx[ch[x][1]]);
     15     rx[x]=max(rx[ch[x][1]],key[x]+sum[ch[x][1]]+rx[ch[x][0]]);
     16     mx[x]=max(max(mx[ch[x][0]],mx[ch[x][1]]),key[x]+rx[ch[x][0]]+lx[ch[x][1]]);
     17 }
     18 
     19 void Cover(int x,int d){
     20     if(!x)return;
     21     key[x]=d;mark[x]=1;
     22     sum[x]=sz[x]*d;
     23     if(d>0)lx[x]=rx[x]=mx[x]=sum[x];
     24     else lx[x]=rx[x]=0,mx[x]=d;
     25 }
     26 
     27 void Flip(int x){
     28     if(!x)return;
     29     swap(ch[x][0],ch[x][1]);
     30     swap(lx[x],rx[x]); //mod Kuang_bin
     31     flip[x]^=1;
     32 }
     33 
     34 void Push_down(int x){
     35     if(mark[x]){
     36         Cover(ch[x][0],key[x]);
     37         Cover(ch[x][1],key[x]);
     38         mark[x]=0;
     39     }
     40     if(flip[x]){
     41         Flip(ch[x][0]);
     42         Flip(ch[x][1]);
     43         flip[x]=0;
     44     }
     45 }
     46 
     47 void Rotate(int x){
     48     int y=fa[x],g=fa[y],c=ch[y][1]==x;
     49     ch[y][c]=ch[x][c^1];fa[ch[y][c]]=y;
     50     ch[x][c^1]=y;fa[y]=x;fa[x]=g;
     51     if(g)ch[g][ch[g][1]==y]=x;
     52     Push_up(y);
     53 }
     54 
     55 void Splay(int x,int g=0){
     56     for(int y;(y=fa[x])!=g;Rotate(x))
     57         if(fa[y]!=g)
     58             Rotate((ch[fa[y]][1]==y)==(ch[y][1]==x)?y:x);
     59     if(!g)rt=x;
     60     Push_up(x);        
     61 }
     62 
     63 void Rtr(int k,int g=0){
     64     int p=rt;
     65     while(true){
     66         Push_down(p);
     67         if(sz[ch[p][0]]+1==k)break;
     68         if(sz[ch[p][0]]+1<k){
     69             k-=sz[ch[p][0]]+1;
     70             p=ch[p][1];
     71         }
     72         else
     73             p=ch[p][0];
     74     }
     75     Splay(p,g);
     76 }
     77 
     78 int Insert(int x,int l,int r){
     79     int mid=(l+r)>>1,p=++cnt;
     80     fa[p]=x;sz[p]=1;
     81     if(l<mid)ch[p][0]=Insert(p,l,mid-1);
     82     scanf("%d",&key[p]);
     83     if(r>mid)ch[p][1]=Insert(p,mid+1,r);
     84     Push_up(p);    
     85     return p;
     86 }
     87 
     88 void Init(){
     89     cnt=2;rt=1;
     90     mx[1]=mx[2]=-INF;
     91     fa[2]=1;ch[1][1]=2;
     92     ch[ch[rt][1]][0]=Insert(ch[rt][1],1,n);
     93     Push_up(ch[rt][1]);
     94     Push_up(rt);
     95 }
     96 
     97 int main(){
     98     freopen("seq2005.in","r",stdin);
     99     freopen("seq2005.out","w",stdout);
    100     scanf("%d%d",&n,&Q);
    101     Init();mx[0]=-INF;
    102     int l,r,x,d,tot=n+2;
    103     while(Q--){
    104         scanf("%s",s);
    105         if(!strcmp(s,"MAX-SUM")){
    106             Rtr(1);
    107             Rtr(tot,rt);
    108             Push_down(rt);
    109             Push_down(ch[rt][1]);
    110             printf("%d
    ",mx[ch[ch[rt][1]][0]]);
    111         }
    112         else if(!strcmp(s,"INSERT")){
    113             scanf("%d%d",&l,&x);l+=1;
    114             Rtr(l);Rtr(l+1,rt);
    115             Push_down(rt);tot+=x;
    116             Push_down(ch[rt][1]);
    117             ch[ch[rt][1]][0]=Insert(ch[rt][1],1,x);
    118             Push_up(ch[rt][1]);
    119             Push_up(rt);
    120         }
    121         else if(!strcmp(s,"DELETE")){
    122             scanf("%d%d",&l,&x);r=l+x+1;
    123             Rtr(l);Rtr(r,rt);tot-=x;
    124             ch[ch[rt][1]][0]=0;
    125             Push_up(ch[rt][1]);
    126             Push_up(rt);
    127         }
    128         else if(!strcmp(s,"REVERSE")){
    129             scanf("%d%d",&l,&x);r=l+x+1;
    130             Rtr(l);Rtr(r,rt);
    131             Flip(ch[ch[rt][1]][0]);
    132             Push_up(ch[rt][1]);
    133             Push_up(rt);
    134         }
    135         else if(!strcmp(s,"MAKE-SAME")){
    136             scanf("%d%d%d",&l,&x,&d);r=l+x+1;
    137             Rtr(l);Rtr(r,rt);
    138             Push_down(rt);
    139             Push_down(ch[rt][1]);
    140             Cover(ch[ch[rt][1]][0],d);
    141             Push_up(ch[rt][1]);
    142             Push_up(rt);
    143         }
    144         else if(!strcmp(s,"GET-SUM")){
    145             scanf("%d%d",&l,&x);r=l+x+1;
    146             Rtr(l);Rtr(r,rt);
    147             Push_down(rt);
    148             Push_down(ch[rt][1]);
    149             printf("%d
    ",sum[ch[ch[rt][1]][0]]);
    150         }
    151     }
    152     return 0;
    153 }

     

     

    尽最大的努力,做最好的自己!
  • 相关阅读:
    Android存储方式之SQLite的使用
    Is there a way to add a badge to an application icon in Android?
    Android SDK Manager更新失败的解决办法
    Android中的Handler机制
    解决SDK下载中遇到的“Connection to https://dl-ssl.google.com refused”问题
    Testlink使用心得
    解决Android Toast重复显示等待时间过长的问题
    Unicode和多字符集的区别
    WEB FARM NLB TEST
    win8.1驱动安装
  • 原文地址:https://www.cnblogs.com/TenderRun/p/5349752.html
Copyright © 2011-2022 走看看