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。

时间: 2024-10-07 05:22:20

NOI2016模拟赛Zbox loves stack的相关文章

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

题意 长为 \(n\) 的序列,询问区间众数,强制在线. \(n\leq 5\times 10^5\). 分析 考虑分块,暴力统计出整块到整块之间的众数次数. 然后答案还可能出现在两边的两个独立的块中,开 \(vector\) 记录每种数字出现的位置集合,然后暴力判断两边两个块中的元素出现的次数.发现并不需要知道具体在 \([l,r]\) 内出现了多少次,而只需要知道 \([l,r]\) 中是否有 \(ans+1\)个该种颜色. 总时间复杂度为 \(O(n\sqrt n)\). 代码 #incl

P5048 [[Ynoi2019模拟赛]Yuno loves sqrt technology III]

为什么我感觉这题难度虚高啊-- 区间众数的出现次数- 计算器算一下 \(\sqrt 500000 = 708\) 然后我们发现这题的突破口? 考虑分块出来[L,R]块的众数出现个数 用 \(\texttt{mx[L][R]}\) 维护就可以了 每次考虑一个L- 然后R指针一直向右移不断的更新到N 这样子做的复杂度因为最多有 \(\sqrt n\) 个块 所以复杂度大概是 \(n\sqrt n\) 实际上还少一点- 然后整块的想好了--单独的怎么处理? 分类讨论 1 \(\texttt{L}\)和

[铁一中OI模拟赛]2017.8.19 Day1

T1 小Z的情书 题目链接 思考: 题目主要难度在于旋转后的位置如何,在手写了样例之后不难发现规律. #include <cstdio> #include <cstring> #define up(a,b,c) for(register int c=a;c<=b;++c) #define down(a,b,c) for(register int c=a;c>=b;--c) const int Maxn=1005; int n; bool Map[Maxn][Maxn],

2017.6.11 校内模拟赛

题面及数据及std(有本人的也有原来的) :2017.6.11 校内模拟赛 T1 自己在纸上模拟一下后就会发现 可以用栈来搞一搞事情 受了上次zsq 讲的双栈排序的启发.. 具体就是将原盘子大小copy一下排个序 用两个指针维护两个数组(原数据 和 排序后的数据), 即分为1数据和2数组 将小于1指针指向的数据的2数组中的数据全部压入栈中 后进行消除, 将栈栈顶元素与当前1数组中的1指针指向的元素进行比较 相同则消除 后重复过程 直至指针超过N 后判断一下是否两个指针都超过了N... #incl

Wannafly模拟赛5 A 思维 D 暴力

Wannafly模拟赛5 A   Split 题意:你有一个大小为??的??????????,每次你可以从你已有的??????????中选择一个大小不为1的??????????,设他的大小为??,然后把它分裂成??和??−??,其中1≤??<??,这样你获得的收益是??∗(??−??)给定??,??,求最少分裂几次才能得到至少??的收益. tags:做题全靠猜系列 1]首先要知道,如果要把一个数 s 分裂成几个固定的数,不管怎么分裂得到的收益是确定的. 这个稍微算几个例子就知道,比如 6 分裂成

计蒜课 八月模拟赛题解

看见机房有大佬上周写了上面的普及信心赛 于是我康了康 8月的提高组模拟赛 9月的还没开始qwq 真的 有点难 主要是我先打开了T2 我再次 对自己的数学产生了怀疑 我现在还是不会写T2 T1 又又又又都错题了 下次重建图 尽量写vector 都写 邻接表 变量差不多的容易搞混 我这个同学变又写错了 T1 :https://nanti.jisuanke.com/t/41086 题目大意就是 一个有向图 删一个点 把与他直接和间接 相连的点 删掉 然后 求删掉所有点的最小最大代价 : 为了避免这个环

10月15日模拟赛题解

10月15日模拟赛题解 A 树 Description 给定一棵 \(n\) 个节点的树,每个节点有两个参数 \(a,~b\),对于每个节点,求子树中参数为 \(b\) 的所有节点的 \(a\) 之和 Limitations \(100\%\) \(1 \leq b \leq n \leq 10^5,~a \leq 1000\) \(60\%\) \(1 \leq b,n\leq 1000\) \(30\%\) \(1 \leq b, n \leq 10\) Solution 对于 \(30\%

10.22 模拟赛

10.22 模拟赛 T1 染色 考虑每个连通块删成一棵树就好了. mmp场上就我路径压缩写炸.... #include<iostream> #define MAXN 200006 using namespace std; int n , m; int fa[MAXN] , siz[MAXN] , book[MAXN] , sz[MAXN]; int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); } int main() {

4.3 省选模拟赛 石子游戏 树上博弈

注意观察题目 每个点都只能将石子给自己的两个儿子 且石子个数>=1. 显然 这是一个阶梯NIM. 只有和最后一层的奇偶性相同的层才会有贡献 证明也很显然. 那么这其实就是近乎NIM游戏了 胜负自然取决于所有有贡献的石子堆的异或和. 但是 上午我傻了的一点 没有分清SG函数和NIM游戏的联系. 在NIM游戏中SG函数其实就是每个有贡献的石子堆的石子数. 再来看这道题 由于异或和一定 暴力枚举移动哪一堆石子 判断是否可行即可. 这个操作其实是 NIM游戏的证明问题了.解决的方案是 观察一下移动后造成