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;
}
原文地址:https://www.cnblogs.com/rrsb/p/8561287.html