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

    题目链接:bzoj1500

    这是一篇补档博客

    讲真,出题人出这种看起来十分模板,几乎没有思维难度,但是细节贼多,考场上几乎不可能写高分的题目出出来的心态是什么

    就这个题,前四个操作几乎是清一色的画风——把要操作的东西单独建成一颗平衡树(splay),然后各种左右儿子找

    第五个操作直接维护,第六个类似于分治的时候,维护左端点起始最大值、右端点起始最大值、包含该点及其子树的最大值。就做完了,哦,为了内存不炸回收一下delete的节点编号以下次使用

    但是细节巨多啊。。。几乎是完全不可能在考场上调出来啊

    所以这种题真的只适合养性了吧。。。

    献上6k代码

    #include<iostream>
    #include<string.h>
    #include<string>
    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<vector>
    #include<queue>
    #include<map>
    using namespace std;
    #define int long long
    const int maxd=1000000007,N=100000;
    const double pi=acos(-1.0);
    typedef long long ll;
    struct node{
        int ch[2],fa,same,rev;
        ll sum,lsum,val,rsum,siz,maxsum;
        void init(int v)
        {
            siz=1;val=v;sum=v;
            same=0;rev=0;
            ch[0]=0;ch[1]=0;
            lsum=max(v,0ll);rsum=lsum;maxsum=v;
        }
    }tree[600000];
    queue<int> q;
    int n,qsiz,tot=0,root=0,a[600000];
    char s[100];
    
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
        while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
        return x*f;
    }
    
    void pushup(int x)
    {
        int l=tree[x].ch[0],r=tree[x].ch[1];
        tree[x].siz=tree[l].siz+tree[r].siz+1;
        tree[x].sum=tree[l].sum+tree[r].sum+tree[x].val;
        tree[x].maxsum=max(tree[l].maxsum,max(tree[r].maxsum,tree[l].rsum+tree[x].val+tree[r].lsum));
        tree[x].lsum=max(tree[l].lsum,tree[l].sum+tree[x].val+tree[r].lsum);
        tree[x].rsum=max(tree[r].rsum,tree[r].sum+tree[x].val+tree[l].rsum);
    }
    
    void pushdown(int x)
    {
        int l=tree[x].ch[0],r=tree[x].ch[1];
        if (tree[x].same)
        {
            tree[x].same=0;tree[x].rev=0;
            if (l)
            {
                tree[l].same=1;tree[l].val=tree[x].val;tree[l].sum=tree[x].val*tree[l].siz;
            }
            if (r)
            {
                tree[r].same=1;tree[r].val=tree[x].val;tree[r].sum=tree[x].val*tree[r].siz;
            }
            if (tree[x].val>=0)
            {
                if (l) tree[l].lsum=tree[l].rsum=tree[l].maxsum=tree[l].sum;
                if (r) tree[r].lsum=tree[r].rsum=tree[r].maxsum=tree[r].sum;
            }
            else 
            {
                if (l) {tree[l].lsum=0;tree[l].rsum=0;tree[l].maxsum=tree[x].val;}
                if (r) {tree[r].lsum=0;tree[r].rsum=0;tree[r].maxsum=tree[x].val;}
            }
        }
        if (tree[x].rev)
        {
            tree[x].rev^=1;
            if (l) tree[l].rev^=1;
            if (r) tree[r].rev^=1;
            swap(tree[l].lsum,tree[l].rsum);swap(tree[r].lsum,tree[r].rsum);
            swap(tree[l].ch[0],tree[l].ch[1]);swap(tree[r].ch[0],tree[r].ch[1]);
        }
    }
    
    void rotate(int x)
    {
        int y=tree[x].fa,z=tree[y].fa,k=(tree[y].ch[1]==x);
        tree[z].ch[tree[z].ch[1]==y]=x;
        tree[x].fa=z;
        tree[y].ch[k]=tree[x].ch[k^1];
        tree[tree[x].ch[k^1]].fa=y;
        tree[x].ch[k^1]=y;tree[y].fa=x;
        pushup(y);pushup(x);
    }
    
    void splay(int x,int goal)
    {
        while (tree[x].fa!=goal)
        {
            int y=tree[x].fa,z=tree[y].fa;
            if (z!=goal)
            {
                if ((tree[y].ch[1]==x)^(tree[z].ch[1]==y)) rotate(x);else rotate(y);
            }
            rotate(x);
        }
        if (!goal) root=x;
    }
    
    int rnk(int k)
    {
        int now=root;
        //cout << k << endl;
        while (now)
        {
            pushdown(now);
            if (tree[tree[now].ch[0]].siz+1<k) 
                {k-=(tree[tree[now].ch[0]].siz+1);now=tree[now].ch[1];}
            else if (tree[tree[now].ch[0]].siz+1==k) return now;
            else now=tree[now].ch[0];
            //cout << now << " " << k << endl;
        }
    }
    
    int build(int l,int r,int fa)
    {
        if (l>r) return 0;
        int mid=(l+r)>>1,now=q.front();q.pop();qsiz--;
        if (l==r)
        {
            tree[now].fa=fa;
            tree[now].init(a[mid]);
            return now;
        }
        tree[now].val=a[mid];tree[now].maxsum=a[mid];tree[now].fa=fa;
        tree[now].ch[0]=build(l,mid-1,now);
        tree[now].ch[1]=build(mid+1,r,now);
        pushup(now);
        return now;
    }
    
    void clr(int x)
    {
        tree[x].maxsum=-maxd;
        tree[x].fa=0;tree[x].ch[0]=0;tree[x].ch[1]=0;
        tree[x].lsum=0;tree[x].rsum=0;tree[x].siz=0;tree[x].rev=0;
        tree[x].same=0;
    }
    
    void reuse(int x)
    {
        if (!x) return;
        q.push(x);qsiz++;
        if (tree[x].ch[0]) reuse(tree[x].ch[0]);
        if (tree[x].ch[1]) reuse(tree[x].ch[1]);
        clr(x);
    }
    
    void insert()
    {
        int pos=read(),tot=read(),i;
        if (!tot) return;
        for (i=1;i<=tot;i++) a[i]=read();
        int l=rnk(pos+1),r=rnk(pos+2);
        splay(l,0);splay(r,l);
        tree[r].ch[0]=build(1,tot,r);
        pushup(r);pushup(l);
    }
    
    void del()
    {
        int pos=read(),tot=read(); 
        if (!tot) return;
        int l=rnk(pos),r=rnk(pos+tot+1);
        //cout << l << " " << r << endl;
        splay(l,0);splay(r,l);
        reuse(tree[r].ch[0]);
        tree[r].ch[0]=0;
        pushup(r);pushup(l);
    }
    
    void rever()
    {
        int pos=read(),tot=read();
        if (!tot) return;
        int l=rnk(pos),r=rnk(pos+tot+1);
        splay(l,0);splay(r,l);
        int now=tree[r].ch[0];
        if (!tree[now].same)
        {
            tree[now].rev^=1;
            swap(tree[now].ch[0],tree[now].ch[1]);
            swap(tree[now].lsum,tree[now].rsum);
            pushup(r);pushup(l);
        }
    }
    
    void getsum()
    {
        int pos=read(),tot=read();
        //if (!tot) return;
        int l=rnk(pos),r=rnk(pos+tot+1);
        splay(l,0);splay(r,l);
        printf("%lld
    ",tree[tree[r].ch[0]].sum);
    }
    
    void makesame()
    {
        int pos=read(),tot=read(),nowval=read();
        //if (!tot) return;
        int l=rnk(pos),r=rnk(pos+tot+1);
        splay(l,0);splay(r,l);
        int now=tree[r].ch[0];
        tree[now].val=nowval;tree[now].same=1;tree[now].sum=tree[now].siz*nowval;
        if (nowval>=0) 
        {
            tree[now].lsum=tree[now].siz*nowval;
            tree[now].rsum=tree[now].lsum;tree[now].maxsum=tree[now].lsum;
        }
        else
        {
            tree[now].lsum=0;tree[now].rsum=0;tree[now].maxsum=nowval;
        }
        pushup(r);pushup(l);
    }
    
    void maxsum()
    {
        printf("%lld
    ",tree[root].maxsum);
    }
    signed main()
    {
        //freopen("a.in","r",stdin);
        //freopen("a.out","w",stdout);
        n=read();int Q=read(),i;qsiz=505000;
        clr(0);
        for (i=1;i<=550000;i++) q.push(i);
        a[1]=-maxd;a[n+2]=-maxd;
        for (i=1;i<=n;i++) a[i+1]=read();
        root=build(1,n+2,0);
        //for (i=1;i<=n+2;i++) cout << tree[i].sum << " ";cout << endl;
        while (Q--)
        {
            scanf("%s",s);int tot;
            if (s[0]=='I') insert();
            else if (s[0]=='D') del();
            else if (s[0]=='R') rever();
            else if (s[0]=='G') getsum();
            else if ((s[0]=='M') && (s[2]=='K')) makesame();
            else if ((s[0]=='M') && (s[2]=='X')) maxsum();
            //for (i=1;i<=20;i++) cout << tree[i].fa << " ";cout << endl;
        }
        return 0;
    }
    
  • 相关阅读:
    Nginx+IIS+Redis 处理Session共享问题 2
    Nginx+IIS+Redis 处理Session共享问题 1
    [ZooKeeper.net] 1 模仿dubbo实现一个简要的http服务的注册 基于webapi
    使用小技巧使子功能模块不污染主框架
    sqlserver 去除重复的行数据
    setsockopt用法详解
    windows 非窗口定时器
    Redis list 之增删改查
    王垠:如何掌握程序语言(转)
    【练习】整树转换为16进制的字符串的函数
  • 原文地址:https://www.cnblogs.com/encodetalker/p/10807248.html
Copyright © 2011-2022 走看看