bzoj3065带插入区间K小值
来源:互联网 发布:新手入门编程语言 编辑:程序博客网 时间:2024/05/21 14:02
这题其实好像很难,但是听werkeytom_ftd说可以用块链水,于是就很开心地去打了个块状链表套主席树,插入操作就直接插到一个块中,注意如果块的大小2*block就将块分开,注意每一个修改或插入都要修改后继的状态,贴代码:
#include<iostream>#include<algorithm>#include<cstdio>#include<cmath>#include<cstring>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int N = 35010;const int M = 610;const int lim = 70000;int root[M][M],s[M],a[M][M],next[M],m;struct point{ int l,r,tot,p;}tree[M*M*2*18];int tot;int n,q,block,lastans,dep,u1,v1,u2,v2;int rt[M];int tt[M*M*2*18],head,tail;void find(int x,int &u1,int &v1){ int ss=0,last=0; for(int i=1;i;i=next[i]){ if (ss+s[i]>=x||next[i]==0){ u1=i; v1=x-ss; break; } ss+=s[i]; }}void prepare(){ fo(i,1,tot)tt[i]=i; head=tail=0;}int getp(){ head=head%tot+1; return tt[head];}void putp(int x){ tail=tail%tot+1; tt[tail]=x;}void clear(int x){ if (!x)return; putp(x); clear(tree[x].p);}void inse(int l,int r,int qf,int &now,int x,int v){ tree[now=getp()]=tree[qf]; tree[now].tot+=v; if (l==r)return; int mid=(l+r)/2; if (x<=mid){ inse(l,mid,tree[qf].l,tree[now].l,x,v); tree[now].p=tree[now].l; } else{ inse(mid+1,r,tree[qf].r,tree[now].r,x,v); tree[now].p=tree[now].r; }}int getans(int l,int r,int k){ if (l==r)return l; int mid=(l+r)/2,ss=0; if (u1!=u2){ fo(i,v1,s[u1])if (l<=a[u1][i]&&a[u1][i]<=mid)ss++; fo(i,1,v2)if (l<=a[u2][i]&&a[u2][i]<=mid)ss++; if (next[u1]!=u2) for(int i=next[u1];i!=u2;i=next[i]) ss+=tree[tree[rt[i]].l].tot; } else fo(i,v1,v2)if (l<=a[u1][i]&&a[u1][i]<=mid)ss++; if (ss>=k){ for(int i=u1;i!=u2;i=next[i]) rt[i]=tree[rt[i]].l; return getans(l,mid,k); } else{ for(int i=u1;i!=u2;i=next[i]) rt[i]=tree[rt[i]].r; return getans(mid+1,r,k-ss); }}int main(){ scanf("%d",&n); tot=360000*2*18; prepare(); block=sqrt(n)+1; fo(i,1,n){ int x; scanf("%d",&x); int u=(i-1)/block+1,v=(i-1)%block+1; inse(0,lim,root[u][v-1],root[u][v],a[u][v]=x,1); } int u=(n-1)/block; fo(i,1,u){ next[i]=i+1; s[i]=block; } int tim=0; s[u+1]=n-u*block; m=u+1; scanf("%d",&q); fo(haha,1,q){ char ch; while(ch=getchar(),ch<'A'||ch>'Z'); if (ch=='Q'){ int x,y,k; scanf("%d%d%d",&x,&y,&k); x^=lastans; y^=lastans; k^=lastans; find(x,u1,v1); find(y,u2,v2); for(int i=u1;i!=u2;i=next[i])rt[i]=root[i][s[i]]; lastans=getans(0,lim,k); printf("%d\n",lastans); tim++; } if (ch=='M'){ int x,val; scanf("%d%d",&x,&val); x^=lastans; val^=lastans; find(x,u1,v1); a[u1][v1]=val; fo(i,v1,s[u1]){ clear(root[u1][i]); inse(0,lim,root[u1][i-1],root[u1][i],a[u1][i],1); } } if (ch=='I'){ int x,val; scanf("%d%d",&x,&val); x^=lastans; val^=lastans; find(x,u1,v1); if (s[u1]+1<block*2){ s[u1]++; fd(i,s[u1],v1+1)a[u1][i]=a[u1][i-1]; a[u1][v1]=val; fo(i,v1,s[u1]){ clear(root[u1][i]); inse(0,lim,root[u1][i-1],root[u1][i],a[u1][i],1); } } else{ if (v1<=block){ s[++m]=block; fo(i,1,block) inse(0,lim,root[m][i-1],root[m][i],a[m][i]=a[u1][i+block-1],1); s[u1]=block; next[m]=next[u1]; next[u1]=m; fd(i,s[u1],v1+1)a[u1][i]=a[u1][i-1]; a[u1][v1]=val; fo(i,v1,s[u1]){ clear(root[u1][i]); inse(0,lim,root[u1][i-1],root[u1][i],a[u1][i],1); } } else{ s[++m]=block; v1-=block; fo(i,1,v1-1){ a[m][i]=a[u1][i+block]; inse(0,lim,root[m][i-1],root[m][i],a[m][i],1); } a[m][v1]=val; inse(0,lim,root[m][v1-1],root[m][v1],val,1); fo(i,v1+1,block){ a[m][i]=a[u1][i+block-1]; inse(0,lim,root[m][i-1],root[m][i],a[m][i],1); } s[u1]=block; next[m]=next[u1]; next[u1]=m; } } } } return 0;}
好吧,vfleaking说正解是这样的:http://vfleaking.blog.163.com/blog/static/1748076342013123659818/
0 0
- BZOJ3065 带插入区间K小值
- [bzoj3065]带插入区间K小值
- bzoj3065带插入区间K小值
- BZOJ3065 带插入区间K小值
- bzoj3065: 带插入区间K小值
- 【BZOJ3065】带插入区间K小值
- [bzoj3065]带插入区间K小值 解题报告
- BZOJ3065: 带插入区间K小值(替罪羊树+权值线段树)
- 替罪羊树套线段树 【bzoj3065】 带插入区间k小值
- [bzoj3065]带插入区间K小值 替罪羊树套值域线段树
- BZO3065 带插入区间K小值
- 3065: 带插入区间K小值
- bzoj 3065 带插入区间k小值
- 【 bzoj 3065 】 带插入区间K小值 - 树套树乱搞
- bzoj 3065 带插入区间K小值
- BZOJ 3065: 带插入区间K小值
- BZOJ 3065 带插入区间K小值
- BZOJ 3065 带插入区间K小值 替罪羊树套线段树
- 51单片机定时器中断函数中变量初始化的问题
- 编码问题
- C++走向远洋——(项目二、存储班长信息的学生类、派生)
- SSH之Hibernate
- 图像二值化 python
- bzoj3065带插入区间K小值
- 时间友元
- HDU,1874,畅通工程续
- 动态规划
- 启动eclipse出现 Error when loading the SDK
- NYOJ——301递推求值(矩阵快速幂)
- C++第5次作业
- 微信红包接龙的数学分析
- 栈