洛谷P3380:二逼平衡树 (树套树)
来源:互联网 发布:云计算培训班 编辑:程序博客网 时间:2024/05/17 23:52
题目传送门:https://www.luogu.org/problemnew/show/3380
题目分析:为什么我要把这道模板题写在博客上呢?因为我想记录一个卡常的小技巧。骗访问量
这题我是考noip之前码的,写的是坐标线段树套动态开节点的权值线段树,虽然空间是
多次修改后还是T3个点,我决定弃坑了。今天早上我忽然想到一个很有力的优化:如果权值线段树已经走到空节点,就不要再往下走,直接退出。结果900多ms卡过了这题QAQ。
CODE:
#include<iostream>#include<string>#include<cstring>#include<cmath>#include<cstdio>#include<cstdlib>#include<stdio.h>#include<algorithm>using namespace std;const int maxn=50100;const int maxl=21;const int oo=2147483647;struct Tnode{ int sum; Tnode *lson,*rson;} tree[maxn*maxl*maxl];Tnode *Seg[maxn<<2];Tnode *Root[maxl<<1];int cur=-1,num;struct data{ int l,r,k,val,id,Time,opt;} work[maxn*3];int temp;int a[maxn];int b[maxn<<1];int n,m;bool Comp1(data x,data y){ return x.val<y.val;}bool Comp2(data x,data y){ return x.Time<y.Time;}Tnode *New_node(){ cur++; tree[cur].sum=0; tree[cur].lson=tree[cur].rson=tree; return tree+cur;}void Build(int root,int L,int R){ Seg[root]=tree; if (L==R) return; int mid=(L+R)>>1; int Left=root<<1; int Right=Left|1; Build(Left,L,mid); Build(Right,mid+1,R);}int Query(Tnode *root,int L,int R,int x,int y){ if ( y<L || R<x || root==tree ) return 0;//root==tree的时候退出,这是个很有力的优化!! if ( x<=L && R<=y ) return root->sum; int mid=(L+R)>>1; int vl=Query(root->lson,L,mid,x,y); int vr=Query(root->rson,mid+1,R,x,y); return (vl+vr);}int Ask(int root,int L,int R,int x,int y,int v){ if ( y<L || R<x ) return 0; if ( x<=L && R<=y ) return Query(Seg[root],1,temp,1,v); int mid=(L+R)>>1; int Left=root<<1; int Right=Left|1; int vl=Ask(Left,L,mid,x,y,v); int vr=Ask(Right,mid+1,R,x,y,v); return (vl+vr);}void Push(int root,int L,int R,int x,int y){ if ( y<L || R<x ) return; if ( x<=L && R<=y ) { Root[++num]=Seg[root]; return; } int mid=(L+R)>>1; int Left=root<<1; int Right=Left|1; Push(Left,L,mid,x,y); Push(Right,mid+1,R,x,y);}int Find(int L,int R,int Rank){ if (L==R) return L; int Left=0,mid=(L+R)>>1; for (int i=1; i<=num; i++) Left+=Root[i]->lson->sum; if (Rank<=Left) { for (int i=1; i<=num; i++) Root[i]=Root[i]->lson; return Find(L,mid,Rank); } else { Rank-=Left; for (int i=1; i<=num; i++) Root[i]=Root[i]->rson; return Find(mid+1,R,Rank); }}void Update(Tnode *&root,int L,int R,int x,int v){ if (root==tree) root=New_node(); if (L==R) { root->sum+=v; return; } int mid=(L+R)>>1; if (x<=mid) Update(root->lson,L,mid,x,v); else Update(root->rson,mid+1,R,x,v); root->sum=root->lson->sum+root->rson->sum;}void Insert(int root,int L,int R,int x,int v){ Update(Seg[root],1,temp,v,1); if (L==R) return; int mid=(L+R)>>1; int Left=root<<1; int Right=Left|1; if (x<=mid) Insert(Left,L,mid,x,v); else Insert(Right,mid+1,R,x,v);}void Delete(int root,int L,int R,int x,int v){ Update(Seg[root],1,temp,v,-1); if (L==R) return; int mid=(L+R)>>1; int Left=root<<1; int Right=Left|1; if (x<=mid) Delete(Left,L,mid,x,v); else Delete(Right,mid+1,R,x,v);}int main(){ freopen("3380.in","r",stdin); freopen("3380.out","w",stdout); scanf("%d%d",&n,&m); for (int i=1; i<=n; i++) { scanf("%d",&a[i]); work[i].val=a[i]; work[i].l=i; work[i].opt=3; } int x=n; for (int i=1; i<=m; i++) { x++; scanf("%d",&work[x].opt); if (work[x].opt!=3) { scanf("%d%d",&work[x].l,&work[x].r); if (work[x].opt==2) scanf("%d",&work[x].k); else scanf("%d",&work[x].val); } else { work[x].opt=6; scanf("%d",&work[x].l); work[x].val=a[ work[x].l ]; x++; work[x].opt=3; scanf("%d",&work[x].val); work[x].l=work[x-1].l; a[ work[x].l ]=work[x].val; } } for (int i=1; i<=x; i++) work[i].Time=i; sort(work+1,work+x+1,Comp1); temp=work[1].id=1; for (int i=2; i<=x; i++) if (work[i-1].val==work[i].val) work[i].id=temp; else work[i].id=++temp,b[temp]=work[i].val; sort(work+1,work+x+1,Comp2); New_node(); Build(1,1,n); for (int i=1; i<=x; i++) { if (work[i].opt==1) { int ans=Ask(1,1,n,work[i].l,work[i].r,work[i].id-1)+1; printf("%d\n",ans); } if (work[i].opt==2) { num=0; Push(1,1,n,work[i].l,work[i].r); int ans=Find(1,temp,work[i].k); printf("%d\n",b[ans]); } if (work[i].opt==3) Insert(1,1,n,work[i].l,work[i].id); if (work[i].opt==4) { int ans; int Rank=Ask(1,1,n,work[i].l,work[i].r,work[i].id-1); if (!Rank) ans=-oo; else { num=0; Push(1,1,n,work[i].l,work[i].r); ans=b[ Find(1,temp,Rank) ]; } printf("%d\n",ans); } if (work[i].opt==5) { int ans; int Rank=Ask(1,1,n,work[i].l,work[i].r,work[i].id); if (Rank==work[i].r-work[i].l+1) ans=oo; else { Rank++; num=0; Push(1,1,n,work[i].l,work[i].r); ans=b[ Find(1,temp,Rank) ]; } printf("%d\n",ans); } if (work[i].opt==6) Delete(1,1,n,work[i].l,work[i].id); } //printf("%d\n",sizeof(tree)>>20); return 0;}
阅读全文
0 0
- 洛谷P3380:二逼平衡树 (树套树)
- 二逼平衡树(树套树)
- 二逼平衡树(树套树)
- BZOJ 3196 二逼平衡树 树套树
- bzoj 3196 二逼平衡树【树套树】
- bzoj 3196 二逼平衡树 树套树
- [树套树] BZOJ3196: 二逼平衡树
- BZOJ 3196 二逼平衡树 树套树
- bzoj3196 二逼平衡树
- Bzoj3196 二逼平衡树
- 【模板】二逼平衡树
- BZOJ3196 二逼平衡树
- bzoj 3196/tyvj p1730 二逼平衡树 树套树
- HYSBZ 3196Tyvj 1730 二逼平衡树(树套树)
- 【bzoj3196】Tyvj 1730 二逼平衡树 树套树
- 树套树——BZOJ3196/Luogu3380 二逼平衡树
- BZOJ 3196: Tyvj 1730 二逼平衡树 树套树
- bzoj 3196: Tyvj 1730 二逼平衡树 树套树
- 网络安全基础
- tf.equal(x, y, name=None)
- SDK创建一个非模态,无资源窗口
- 1.7 空格分隔输出
- 二分图浅识
- 洛谷P3380:二逼平衡树 (树套树)
- 浅谈typedef和#define
- React Native开发之React Navigation的StackNavigator 详解
- 【信号与系统】私人回顾
- (bootstrap)
- LightOJ 1027 Dangerous Maze【期望】
- 1.8 输出浮点数
- 挑战程序设计2.3 多重集组合数 POJ3046
- 移除数组中的元素(返回新数组)