zoukankan      html  css  js  c++  java
  • NOI 十连测 Zbox loves stack

    题目描述 (4s,1G)
    从小热爱计算机的Zbox开始玩栈了.Zbox有n个栈,他命令你支持如下操作:
    *.把第l个栈到第r个栈都压入一个元素x
    *.把第l个栈到第r个栈都弹出栈顶(若栈为空则无视)
    *.询问第s个栈的第k个元素是多少(栈顶为第一个元素)
    输入描述
    第一行2个数n,q
    接下来q行,每行第一个数为t
    若t为0,输入l,r,x,把第l个栈到第r个栈都压入一个元素x
    若t为1,输入l,r,把第l个栈到第r个栈都弹出栈顶
    若t为2,输入s,k,询问第s个栈的第k个元素是多少,若栈中没有k个元素则输出"Error"
    输出描述
    对于每一个t=2的操作,输出一行"Error"或一个数表示答案

    数据规模
    对于10%的数据,n<=5000,q<=5000
    对于30%的数据,n<=100000,q<=30000
    对于另外10%的数据,保证没有t=1的操作
    对于另外10%的数据,所有t=0的操作满足l=r
    对于另外10%的数据,所有t=1的操作满足l=r
    对于另外10%的数据,所有t=2的操作满足k=1
    对于另外10%的数据,保证不会输出"Error"
    对于100%的数据,n<=1000000,q<=100000,所有输入的数在[0,2^31-1]之间

    SOL:  我们可以信仰暴力N方过百万,然后这题目就过了

       这题 的标算 也 是O(N log ^2)的。

      我们考虑线段树维护区间,那么我们需要一种数据结构来维护查询K大元素,快速数据下传。 我们发现 fhq treap可以胜任。我们同时要求前后数据的修改无关,那么我们可以可持久化这玩意。

    #pragma GCC optimize("-O3")
    #include<bits/stdc++.h>
    #define rr NULL
    #define N 1000005
    using namespace std;
    #define sight(x) ('0'<=x&&x<='9')
    inline void read(int &x){
        static char c;
        for (c=getchar();!sight(c);c=getchar());
        for (x=0;sight(c);c=getchar())x=x*10+c-48;
    }
    void write(int x){if (x<10) {putchar('0'+x); return;} write(x/10); putchar('0'+x%10);}
    inline void writeln(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar('
    '); }
    inline void writel(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar(' '); }
    inline int rop(){
        static int x=23333;
        return x^=x<<13,x^=x>>17,x^=x<<5;
    }
    int lazy[N<<2];
    struct T{
         int key,val,siz; T* son[2];
         T() {}
         T(int x){siz=1;key=x;val=rop();son[0]=son[1]=rr;}
         void be() {
               siz=1;
               if (son[0]) siz+=son[0]->siz;
               if (son[1]) siz+=son[1]->siz;
         }
         inline int ibt() {return son[0]?son[0]->siz+1:1;}
         inline int Siz() {return this!=0?siz:0;}
    };
    T *root[N<<2];
    struct Tre{
          void split(T* now,int k,T* &x,T* &y) {
              if (!now) {x=y=rr; return;}
              int cmp=now->ibt();
              if (k<cmp) y=new T(),*y=*now,split(y->son[0],k,x,y->son[0]),y->be();
              else x=new T(),*x=*now,split(x->son[1],k-cmp,x->son[1],y),x->be();
            }
            T* merge(T* x,T* y) {
                 if (!x) return y; if (!y) return x;
                 T *X=new T();
                 if (x->val<y->val){
                       *X=*x; X->son[1]=merge(X->son[1],y);
                 } else { 
                    *X=*y; X->son[0]=merge(x,X->son[0]); 
                 }
                 X->be(); return X;
            }
            int t; T* xt,*yt,*zt;
            inline void del(int rot,int x) {
                t=min(x,root[rot]->Siz());
                split(root[rot],root[rot]->Siz()-t,xt,yt);
                root[rot]=xt; 
                lazy[rot]+=(x-t);
            }
            inline void ins(int rot,int x) {
                root[rot]=merge(root[rot],new T(x));
            }
            void que(int k,int x){
                zt=root[k];
                if (zt->Siz()<x) {printf("Error
    "); return;}
                t=zt->siz-x+1;
                split(zt,t,xt,yt);
                split(xt,t-1,xt,yt);
                writeln(yt->key);
            }
    }treap;
    #define Mid (l+r>>1)
    struct Segment{
         inline void pd(int k,bool op){
               if (op) {lazy[k]=0; return;}
               if (lazy[k]>0) {
                     treap.del(k<<1,lazy[k]);
                     treap.del(k<<1|1,lazy[k]);
                     lazy[k]=0;
                 }
                 root[k<<1]=treap.merge(root[k<<1],root[k]);
                 root[k<<1|1]=treap.merge(root[k<<1|1],root[k]);
                 root[k]=rr;
         } 
         void ins(int k,int l,int r,int L,int R,int id){
            pd(k,l==r);
            if (L<=l&&r<=R) {treap.ins(k,id); return;}
            if (L<=Mid) ins(k<<1,l,Mid,L,R,id);
            if (R> Mid) ins(k<<1|1,Mid+1,r,L,R,id);
         }
         void del(int k,int l,int r,int L,int R){
            pd(k,l==r);
            if (L<=l&&r<=R) {treap.del(k,1); return;}
            if (L<=Mid) del(k<<1,l,Mid,L,R);
            if (R> Mid) del(k<<1|1,Mid+1,r,L,R);
         }
         void que(int k,int l,int r,int x,int id){
            pd(k,l==r);
            if (l==r) {treap.que(k,id); return;}
            if (x<=Mid) que(k<<1,l,Mid,x,id);
            else que(k<<1|1,Mid+1,r,x,id);
         }
    }Tree;
    int n,q,op,l,r,w;
    signed main () {
         freopen("stack.in","r",stdin);
         freopen("stack.out","w",stdout);
         read(n); read(q);
         while (q--) {
             read(op); read(l); read(r);
             if (op==0) read(w),Tree.ins(1,1,n,l,r,w);
             else if (op==1) Tree.del(1,1,n,l,r);
             else Tree.que(1,1,n,l,r);
    //             cerr<<tot<<endl;
         }
         return 0;
    }
  • 相关阅读:
    错误处理和调试 C++快速入门30
    错误处理和调试 C++快速入门30
    虚继承 C++快速入门29
    多继承 C++快速入门28
    界面设计01 零基础入门学习Delphi42
    鱼C记事本 Delphi经典案例讲解
    界面设计01 零基础入门学习Delphi42
    虚继承 C++快速入门29
    linux系统中iptables防火墙管理工具
    linux系统中逻辑卷快照
  • 原文地址:https://www.cnblogs.com/rrsb/p/8561287.html
Copyright © 2011-2022 走看看