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 }
题目大意: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的主要内容,如果未能解决你的问题,请参考以下文章