NOI2016模拟赛Zbox loves stack

Posted oyzx~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOI2016模拟赛Zbox loves stack相关的知识,希望对你有一定的参考价值。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <algorithm>
  6 using namespace std;
  7 #define PI pair<int,int>
  8 #define fi first
  9 #define se second
 10 #define mp(a,b) make_pair(a,b)
 11 #define maxn 1000005
 12 #define maxk 40000005
 13 int n,q,tot,val[maxk],fa[maxk],son[maxk][2],size[maxk];
 14 void read(int &x){
 15     x=0; int f=1; char ch;
 16     for (ch=getchar();!isdigit(ch);ch=getchar()) if (ch==\'-\') f=-1;
 17     for (;isdigit(ch);ch=getchar()) x=x*10+ch-\'0\'; x*=f;
 18 }
 19 int lazy[maxn<<2],root[maxn<<2];
 20 struct Treap{
 21     int random(int x){return rand()%x+1;}
 22     void updata(int x){
 23         size[x]=size[son[x][0]]+size[son[x][1]]+1;
 24     }
 25     int newnode(int x){
 26         size[++tot]=1,val[tot]=val[x]; return tot;
 27     }
 28     PI split(int x,int y){
 29         if (y==0) return mp(0,x);
 30         if (size[x]==y) return mp(x,0);
 31         PI temp; int nx,ny;
 32         if (size[son[x][0]]>=y){
 33             temp=split(son[x][0],y); nx=newnode(x),son[nx][0]=temp.se,son[nx][1]=son[x][1],updata(nx);
 34             return mp(temp.fi,nx);
 35         }else{
 36             temp=split(son[x][1],y-size[son[x][0]]-1); 
 37             nx=newnode(x),son[nx][1]=temp.fi,son[nx][0]=son[x][0],updata(nx); return mp(nx,temp.se);
 38         }
 39     }
 40     int merge(int x,int y){
 41         int nx,ny;
 42         if (x==0||y==0) return x+y;
 43         if (random(size[x]+size[y])<=size[x]){
 44             nx=newnode(x),son[nx][0]=son[x][0],son[nx][1]=merge(son[x][1],y),updata(nx);
 45             return nx;
 46         }else{
 47             ny=newnode(y),son[ny][1]=son[y][1],son[ny][0]=merge(x,son[y][0]),updata(ny);
 48             return ny;
 49         }
 50     }
 51     void lazypush(int k,int x){
 52         int t=min(x,size[root[k]]);
 53         PI temp; int a,b,c;
 54         temp=split(root[k],size[root[k]]-t);
 55         a=temp.fi,c=temp.se;
 56         root[k]=a; lazy[k]+=(x-t);
 57     }
 58     void insert(int k,int x){
 59         int t=root[k];
 60         int nx=++tot; val[nx]=x,size[nx]=1;
 61         root[k]=merge(root[k],nx);
 62     }
 63     void Query(int k,int x){
 64         int t=root[k]; PI temp; int a,b,c;
 65         if (size[root[k]]<x) printf("Error\\n");
 66         else{
 67             int T=size[t]-x+1;
 68             temp=split(t,T);
 69             a=temp.fi,c=temp.se;
 70             temp=split(a,T-1);
 71             a=temp.fi,b=temp.se;
 72             printf("%d\\n",val[b]);
 73         }
 74     }
 75 }treap;
 76 struct Segment{
 77     void build(int k,int l,int r){
 78         lazy[k]=0;
 79         if (l==r) return; int mid=(l+r)>>1;
 80         build(k*2,l,mid),build(k*2+1,mid+1,r);
 81     }
 82     void pushdown(int k,int op){
 83         if (op==1){
 84             lazy[k]=0; return;
 85         }
 86         if (lazy[k]>0){
 87             treap.lazypush(k*2,lazy[k]);
 88             treap.lazypush(k*2+1,lazy[k]);
 89             lazy[k]=0;
 90         }
 91         root[k*2]=treap.merge(root[k*2],root[k]);
 92         root[k*2+1]=treap.merge(root[k*2+1],root[k]);
 93         root[k]=0;
 94     }
 95     void insert(int k,int l,int r,int x,int y,int z){
 96         pushdown(k,(l==r));
 97         if (l>=x&&r<=y){
 98             treap.insert(k,z);
 99             return;
100         }int mid=(l+r)>>1;
101         if (x<=mid) insert(k*2,l,mid,x,y,z);
102         if (y>mid) insert(k*2+1,mid+1,r,x,y,z);
103     }
104     void Delete(int k,int l,int r,int x,int y){
105         pushdown(k,(l==r));
106         if (l>=x&&r<=y){
107             treap.lazypush(k,1);
108             return;
109         }int mid=(l+r)>>1;
110         if (x<=mid) Delete(k*2,l,mid,x,y);
111         if (y>mid) Delete(k*2+1,mid+1,r,x,y);
112     }
113     void Query(int k,int l,int r,int x,int y){
114         pushdown(k,(l==r));
115         if (l==r&&r==x){
116             treap.Query(k,y);
117             return;
118         }int mid=(l+r)>>1;
119         if (x<=mid) Query(k*2,l,mid,x,y);
120         else Query(k*2+1,mid+1,r,x,y);
121     }
122 }Tree;
123 
124 int main(){
125     srand(20010804);
126     read(n),read(q);
127     memset(root,0,sizeof(root));
128     memset(size,0,sizeof(size));
129     Tree.build(1,1,n);
130     for (int type,l,r,w;q;--q){
131         read(type),read(l),read(r);
132         if (type==0) read(w),Tree.insert(1,1,n,l,r,w);
133         else if (type==1) Tree.Delete(1,1,n,l,r);
134         else Tree.Query(1,1,n,l,r);
135     }
136     return 0;
137 }
View Code

题目大意:Zbox loves stack

题目描述
从小热爱计算机的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分算法,暴力模拟,本还妄想水过满分(雾——)。今天这套题拿了120分纪念一下,不过还是因为出题人太仁道了。

本题正解:这题采用树套树的做法,线段树维护区间,对于线段树的每个节点建立一个treap,首先,这题要求维护一个高级数据结构,支持在该数据结构添加一个节点,删除一个节点,询问第k个位置,这是平衡树能轻松做到的,但是这是区间修改,显然要用到线段树维护,那么怎么下传信息呢,如果要下传x节点的信息,设其两个儿子分别为t1,t2,我们需要做的就是把x与t1,t2分别合并,但是x和其中一个合并后会破坏x的信息,所以我们要将可持久化,我便考虑用线段树套可持久化treap。还有一个细节就是:删除操作,若节点的个数不够,我们打上标记,下传信息时,应先下传标记,再下传之前说的信息。

线段树+可持久化treap。

 

以上是关于NOI2016模拟赛Zbox loves stack的主要内容,如果未能解决你的问题,请参考以下文章

2016NOI冬令营day3

NOI模拟赛Day4

NOI模拟赛Day2

[Ynoi2019模拟赛]Yuno loves sqrt technology III

NOI模拟赛 Day1

[Luogu]5048 [Ynoi2019模拟赛]Yuno loves sqrt technology III[分块]