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

    http://www.lydsy.com/JudgeOnline/problem.php?id=1500

    1、覆盖标记用INF表示无覆盖标记,要求可能用0覆盖

    2、代表空节点的0号节点和首尾的两个虚拟节点,所有有关取max的信息全部设为负无穷,但注意不要无穷相加爆掉int

    3、空间,用一个队列回收已删除的节点的编号

    4、建树的时候采用的笛卡尔树的构造方式,但并没有比错误的忽略优先级的build快多少

    5、手写的max快

    inline int& max(int &x, int &y) { return x > y ? x : y; }

    #define max(x, y) ((x) > (y) ? (x) : (y))

    #include<queue>
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    //#include<algorithm>
     
    using namespace std;
     
    #define N 500005
     
    #define INF 1e9
     
    int tot,root;
     
    int pri[N],val[N];
    int sum[N],mxr[N],mxl[N],mx[N];
    int ch[N][2],siz[N];
    bool rev[N];
    int tag[N];
     
    int pos,cnt,w;
     
    int a[N];
     
    queue<int>trash;
     
    int st[N],top;
     
    void read(int &x)
    {
        x=0; int f=1; char c=getchar();
        while(!isdigit(c)) { if(c=='-') f=-1; c=getchar();}
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar();}
        x*=f;
    }
     
    inline int& max(int &x, int &y) { return x > y ? x : y; }
     
    void update(int x)
    {
        int l=ch[x][0],r=ch[x][1];
        siz[x]=siz[l]+siz[r]+1;
        sum[x]=sum[l]+sum[r]+val[x];
        mx[x]=max(mx[l],mx[r]);
        mx[x]=max(mx[x],mxr[l]+val[x]);
        mx[x]=max(mx[x],mxl[r]+val[x]);
        mx[x]=max(mx[x],mxr[l]+mxl[r]+val[x]);
        mx[x]=max(mx[x],val[x]);
        mxr[x]=max(mxr[r],sum[r]+mxr[l]+val[x]);
        mxr[x]=max(mxr[x],sum[r]+val[x]);
        mxl[x]=max(mxl[l],sum[l]+mxl[r]+val[x]);
        mxl[x]=max(mxl[x],sum[l]+val[x]);
    }
     
    void down(int x)
    {
        if(rev[x])
        {
            int l=ch[x][0],r=ch[x][1];
            if(l)
            {
                swap(ch[l][0],ch[l][1]);
                swap(mxl[l],mxr[l]);
                rev[l]^=1;
            }
            if(r)
            {
                swap(ch[r][0],ch[r][1]);
                swap(mxl[r],mxr[r]);
                rev[r]^=1;
            }
            rev[x]^=1;
        }
        if(tag[x]!=INF)
        {
            int l=ch[x][0],r=ch[x][1];
            if(l)
            {
                val[l]=tag[x];
                sum[l]=mxl[l]=mxr[l]=mx[l]=siz[l]*tag[x];
                tag[l]=tag[x];
            }
            if(r)
            {
                val[r]=tag[x];
                sum[r]=mxl[r]=mxr[r]=mx[r]=siz[r]*tag[x];
                tag[r]=tag[x];
            }
            tag[x]=INF;
        }
    }       
     
    int newnode(int v)
    {
        int now;
        if(!trash.empty()) now=trash.front(),trash.pop();
        else now=++tot;
        siz[now]=1;
        val[now]=v;
        pri[now]=rand();
        tag[now]=INF;
        sum[now]=mx[now]=mxl[now]=mxr[now]=v;
        rev[now]=false;
        ch[now][0]=ch[now][1]=0;
        return now;
    }
     
    int build(int l,int r)
    {
        int now,last; top=0;
        for(int i=l;i<=r;++i)
        {
            now=newnode(a[i]);
            last=0;
            while(top && pri[st[top]]>pri[now]) 
            {
                update(st[top]);
                last=st[top--];
            }
            if(top) ch[st[top]][1]=now;
            ch[now][0]=last; st[++top]=now;
        }
        while(top) update(st[top--]);
        return st[1];
    }
     
    void split(int now,int p,int &x,int &y)
    {
        if(!now) x=y=0;
        else
        {
            down(now);
            if(p<=siz[ch[now][0]])
            {
                y=now;
                split(ch[now][0],p,x,ch[now][0]);
            }
            else
            {
                x=now;
                split(ch[now][1],p-siz[ch[now][0]]-1,ch[now][1],y);
            }
            update(now);
        }
    }
     
    int merge(int x,int y)
    {
        if(x) down(x);
        if(y) down(y);
        if(!x || !y) return x+y;
        if(pri[x]<pri[y])
        {
            ch[x][1]=merge(ch[x][1],y);
            update(x);
            return x;
        }
        else
        {
            ch[y][0]=merge(x,ch[y][0]);
            update(y);
            return y;
        }
    }
     
    int find(int k)
    {
        int now=root;
        while(1)
        {
            down(now);
            if(k<=siz[ch[now][0]]) now=ch[now][0];
            else
            {
                k-=siz[ch[now][0]];
                if(k==1) return now;
                k--;
                now=ch[now][1];
            }
        }
    }
         
    void insert()
    {
        read(pos); read(cnt);
        pos++;
        for(int i=1;i<=cnt;++i) read(a[i]);
        int rt=build(1,cnt);
        int a,b;
        split(root,pos,a,b);
        int e=merge(a,rt);
        root=merge(e,b);
    }   
     
    void del(int x)
    {
        if(!x) return;
        trash.push(x);
        del(ch[x][0]);
        del(ch[x][1]);
    }
     
    void solve(int ty)
    {
        read(pos); read(cnt);
        pos++;
        int a,b;
        split(root,pos+cnt-1,a,b);
        int c,d;
        split(a,pos-1,c,d);
        if(ty==1) 
        {
            del(d);
            root=merge(c,b);
            return;
        }
        if(ty==2) 
        {
            read(w);
            tag[d]=w;
            val[d]=w;
            sum[d]=mxl[d]=mxr[d]=mx[d]=siz[d]*w;
        }
        else if(ty==3) 
        {
            rev[d]^=1;
            swap(ch[d][0],ch[d][1]);
            swap(mxl[d],mxr[d]);
        }
        else if(ty==4) printf("%d
    ",sum[d]);
        root=merge(merge(c,d),b);
    }
     
    int main()
    {
        mx[0]=mxl[0]=mxr[0]=-7e8;
        int n,m;
        read(n); read(m);
        for(int i=2;i<=n+1;++i) read(a[i]);
        a[1]=a[n+2]=-7e8;
        root=build(1,n+2);
        char s[12];
        while(m--)
        {
            scanf("%s",s);
            if(s[0]=='I') insert();
            else if(s[0]=='D') solve(1);
            else if(s[2]=='K') solve(2);
            else if(s[0]=='R') solve(3);
            else if(s[0]=='G') solve(4);
            else printf("%d
    ",mx[root]);
        }
    }

    1500: [NOI2005]维修数列

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 15972  Solved: 5312
    [Submit][Status][Discuss]

    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

  • 相关阅读:
    英文、简繁体中文 IT 词汇对照表
    VB.NET 中的 As New 以及型別指定
    使用 ADO.NET 的 ExecuteScalar 方法返回单一值
    适时调整 SqlDataSource 控件的 DataSourceMode 属性
    ADO.NET 2.0 的并行控制与数据存取冲突侦测
    让 ADO.NET 2.0 的 SqlCommand 和 SqlDataAdapter 合作
    透过 Socket API 让 PDA 和远程 PC 联机
    探讨 .NET 语言的 using statement 与资源释放
    让 user control 中的 Button 也能启用验证
    dotNET 語言中可提升效能的邏輯運算子
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8400089.html
Copyright © 2011-2022 走看看