bzoj1901(动态区间第k大,树套树)

来源:互联网 发布:淘宝虚假交易不清洗 编辑:程序博客网 时间:2024/05/16 19:56

表示主席树+树状数组懒得打了,学了树套树水过。。。

 

线段树套平衡树

#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<algorithm>using namespace std;const int N=12005;const int inf=0x3f3f3f3f;int n,m,tmp;int c[N];inline int read(){int ans,f=1;char ch;while ((ch=getchar())<'0'||ch>'9') if (ch=='-') f=-1;ans=ch-'0';while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0';return ans*f;}int tot,size[N*18],fa[N*18],ch[N*18][2],cnt[N*18],val[N*18];struct sigment{int l,r;int rt;void up(int x){size[x]=size[ch[x][0]]+size[ch[x][1]]+cnt[x];}void rot(int x){int y=fa[x],z=fa[y],l,r;if (ch[y][0]==x) l=0;else l=1;r=l^1;if (z)if (ch[z][0]==y) ch[z][0]=x;else ch[z][1]=x;fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;ch[y][l]=ch[x][r];ch[x][r]=y;up(y);}void splay(int x,int k){int y,z;while (fa[x]!=k){y=fa[x],z=fa[y];if (z!=k)if (ch[z][0]==y^ch[y][0]==x) rot(x);else rot(y);rot(x);}if (k==0) rt=x;up(x);}void insert(int x){if (rt==0) {rt=++tot;size[rt]=cnt[rt]=1;val[rt]=x;return ;}int k=rt;while (true){size[k]++;if (val[k]==x) {cnt[k]++;return;}int y=ch[k][x>val[k]];if (!y){++tot;fa[tot]=k;val[tot]=x;cnt[tot]=size[tot]=1;ch[k][x>val[k]]=tot;k=tot;break;}k=y;}splay(k,0);}int find(int i,int x){if (val[i]==x) return i;if (val[i]>x) return find(ch[i][0],x);else return find(ch[i][1],x);}int small_num(int i,int x){if (i==0) return 0;if (val[i]==x) return size[ch[i][0]];if (val[i]>x) return small_num(ch[i][0],x);return size[ch[i][0]]+cnt[i]+small_num(ch[i][1],x);}void del(int x){int k=find(rt,x);splay(k,0);if (cnt[k]>1){cnt[k]--;size[k]--;return ;}if (ch[k][0]==0&&ch[k][1]==0) {rt=0;return ;}if (ch[k][0]==0) {rt=ch[k][1];fa[rt]=0;return ;}if (ch[k][1]==0) {rt=ch[k][0];fa[rt]=0;return ;}int y=ch[k][0];while (ch[y][1]) y=ch[y][1];splay(y,k);rt=y;fa[rt]=0;fa[ch[k][1]]=y;ch[y][1]=ch[k][1];up(y);}}a[N*4];void build(int i,int l,int r){a[i].l=l;a[i].r=r;for (int j=l;j<=r;j++) a[i].insert(c[j]);if (l==r) return ;int mid=(l+r)>>1;build(i<<1,l,mid);build(i<<1|1,mid+1,r);}void updata(int i,int l,int k){a[i].del(c[l]);a[i].insert(k);if (a[i].l==a[i].r) return ;int mid=(a[i].l+a[i].r)>>1;if (mid>=l) updata(i<<1,l,k);else updata(i<<1|1,l,k);}void find_rank(int i,int l,int r,int x){if (a[i].l==l&&a[i].r==r){tmp+=a[i].small_num(a[i].rt,x);return;}int mid=(a[i].l+a[i].r)>>1;if (mid>=r) find_rank(i<<1,l,r,x);else if (mid<l) find_rank(i<<1|1,l,r,x);else find_rank(i<<1,l,mid,x),find_rank(i<<1|1,mid+1,r,x);}void rank_k(int l,int r,int x){int ml=0,mr=1e9,mid,ans=0;while(ml<=mr){mid=(ml+mr)>>1;tmp=0;find_rank(1,l,r,mid);if (tmp<=x-1){ans=mid;ml=mid+1;}else mr=mid-1;}printf("%d\n",ans);}int main(){scanf("%d%d",&n,&m);for (int i=1;i<=n;i++) scanf("%d",&c[i]);build(1,1,n);int l,r,x;char ch[5];while (m--){scanf("%s",ch);switch(ch[0]){case 'Q':scanf("%d%d%d",&l,&r,&x);rank_k(l,r,x);break;case 'C':scanf("%d%d",&l,&x);updata(1,l,x);c[l]=x;break;}}return 0; } 


总结

1.果然这个数据范围不写读入优化是不行的。。

0 0
原创粉丝点击