洛谷 P2617 Dynamic Rankings(毒瘤卡常题 带修主席树/TLE的树套树)

题目描述
一道垃圾的区间带修第k大写了一天
线段树套splay TLE
优化成两个log TLE
套替罪羊树 TLE
套权值线段树 TLE

算了吧,就当模板带修主席树吧
带修主席树这玩意真暴力
就用个树状数组把一堆线段树套起来
然后求的时候把每个树状数组里的点都暴力提取出来,直接暴力对每个点对应的数统计答案,树上二分
模板题也没什么好说的,垃圾……

代码如下:

#include<bits/stdc++.h>
#define lson tr[now].l
#define rson tr[now].r
using namespace std;

inline int lowbit(int x)
{
	return x&(-x);
}

struct tree
{
	int l,r,sum;
}tr[40000030];

int cnt,rt[400020];
int tota,totb,tmpa[400020],tmpb[400020];
int a[400020],tot,b[400020];
int n,m;

struct que
{
	int kd,l,r,val;
}q[400020];

void insert(int &now,int pre,int l,int r,int pos,int val)
{
	now=++cnt;
	tr[now]=tr[pre];
	tr[now].sum+=val;
	if(l==r)
	{
		return ;
	}
	int mid=(l+r)>>1;
	if(pos<=mid) insert(lson,tr[pre].l,l,mid,pos,val);
	else insert(rson,tr[pre].r,mid+1,r,pos,val);
}

int query(int l,int r,int kk)
{
	if(l==r)
	{
		return b[l];
	}
	int mid=(l+r)>>1;
	int sz=0;
	for(int i=1;i<=tota;i++) sz+=tr[tr[tmpa[i]].l].sum;
	for(int i=1;i<=totb;i++) sz-=tr[tr[tmpb[i]].l].sum;
	if(kk<=sz)
	{
		for(int i=1;i<=tota;i++) tmpa[i]=tr[tmpa[i]].l;
		for(int i=1;i<=totb;i++) tmpb[i]=tr[tmpb[i]].l;
		return query(l,mid,kk);
	}
	else
	{
		for(int i=1;i<=tota;i++) tmpa[i]=tr[tmpa[i]].r;
		for(int i=1;i<=totb;i++) tmpb[i]=tr[tmpb[i]].r;
		return query(mid+1,r,kk-sz);
	}

}

void add(int pos,int val)
{
	int vp=lower_bound(b+1,b+tot+1,a[pos])-b;
	for(int i=pos;i<=n;i+=lowbit(i))
	{
		insert(rt[i],rt[i],1,tot,vp,val);
	}
}

int get(int l,int r,int kk)
{
	tota=0,totb=0;
	for(int i=r;i>0;i-=lowbit(i)) tmpa[++tota]=rt[i];
	for(int i=l-1;i>0;i-=lowbit(i)) tmpb[++totb]=rt[i];
	return query(1,tot,kk);
}

char s[10];

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[++tot]=a[i];
	for(int i=1;i<=m;i++)
	{
		scanf("%s",s);
		if(s[0]=='Q') 
		{
			q[i].kd=0;
			scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].val);
		}
		else
		{
			q[i].kd=1;
			scanf("%d%d",&q[i].l,&q[i].val);
			b[++tot]=q[i].val;
		}
	}
	sort(b+1,b+tot+1);
	tot=unique(b+1,b+tot+1)-b-1;
	for(int i=1;i<=n;i++) add(i,1);
	for(int i=1;i<=m;i++)
	{
		if(q[i].kd)
		{
			add(q[i].l,-1);
			a[q[i].l]=q[i].val;
			add(q[i].l,1);
		}
		else
		{
			printf("%d\n",get(q[i].l,q[i].r,q[i].val));
		}
	}
	// printf("%d\n",cnt);
} 

替罪羊树

#include<bits/stdc++.h>
#define alpha 0.75
using namespace std;

struct tree
{
	int l,r;
}tr[800040];

struct que
{
	int kd,ll,rr,vv;
}q[200020];

struct point
{
	int son[2],real,sz,val,vis;
}t[3000010];

int rt[800040],a[200020];
int sta[3000010],tmp[200020],top,cnt;
int tmp2[800020],tot;
int n,m,ttt;
char op[2];

inline int read()
{
    int f=1,x=0;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    return f*x;
}

void init()
{
	for(int i=1;i<=3000000;i++) sta[++top]=i;
	sort(tmp2+1,tmp2+tot+1);
	tot=unique(tmp2+1,tmp2+tot+1)-tmp2-1;
	for(int i=1;i<=n;i++)
	{
		a[i]=lower_bound(tmp2+1,tmp2+tot+1,a[i])-tmp2;
	}
	for(int i=1;i<=m;i++)
	{
		if(q[i].kd==2) q[i].vv=lower_bound(tmp2+1,tmp2+tot+1,q[i].vv)-tmp2;
	}
}

#define lson t[now].son[0]
#define rson t[now].son[1]

inline int bad(int now)
{
	return (double) t[now].sz*alpha<=(double) max(t[lson].sz,t[rson].sz);
}

void push_up(int now)
{
	t[now].real=t[lson].real+t[rson].real+1;
	t[now].sz=t[lson].sz+t[rson].sz+1;
}

void build(int now)
{
	lson=rson=0;
	t[now].sz=t[now].real=1;
}

void la(int &now,int l,int r)
{
	int mid=(l+r)>>1;
	now=tmp[mid];
	if(l==r) 
	{
		build(now);
		return ;
	}
	if(l<mid) la(lson,l,mid-1);
	else lson=0;
	la(rson,mid+1,r);
	push_up(now);
}

void pia(int now)
{
	if(!now) return ;
	pia(lson);
	if(t[now].vis) tmp[++cnt]=now;
	else sta[++top]=now;
	pia(rson);
}

void rebuild(int &now)
{
	cnt=0;
	pia(now);
	if(cnt>0) la(now,1,cnt);
	else now=0;
}

void insert(int &now,int val)
{
	if(!now)
	{
		now=sta[top--];
		t[now].val=val;
		t[now].vis=1;
		build(now);
		return;
	}
	t[now].real++;
	t[now].sz++;
	if(t[now].val>=val) insert(lson,val);
	else insert(rson,val);
	if(bad(now)) rebuild(now);
}

int get_rk(int now,int val)
{
	int tot=1;
	while(now)
	{
		if(t[now].val>=val) now=lson;
		else tot+=t[now].vis+t[lson].real,now=rson;
	}
	return tot;
}

int get_val(int now,int rk)
{
	while(now)
	{
		if(rk==t[now].vis+t[lson].real&&t[now].vis) return t[now].val;
		if(t[now].vis+t[lson].real>=rk) now=lson;
		else rk-=t[now].vis+t[lson].real;
	}
} 

void del_rk(int &now,int rk)
{
	if(t[now].vis&&t[now].vis+t[lson].real==rk)
	{
		t[now].real--;
		t[now].vis=0;
		return ;
	}
	t[now].real--;
	if(t[now].vis+t[lson].real>=rk) del_rk(lson,rk);
	else del_rk(rson,rk-t[now].vis-t[lson].real);
}

void del_val(int &now,int val)
{
	int rk=get_rk(now,val);
	del_rk(now,rk);
	if((double)t[now].sz*alpha>=t[now].real) rebuild(now);
}

void debug(int now)
{
    if(lson) debug(lson);
    if(t[now].vis) printf("%d ",t[now].val);
    if(rson) debug(rson);
}

#undef lson
#undef rson

#define lson root<<1
#define rson root<<1|1
void build(int root,int l,int r)
{
	rt[root]=sta[top--];
	tr[root].l=l;
	tr[root].r=r;
	if(l==r)
	{
		return;
	}
	int mid=(l+r)>>1;
	build(lson,l,mid);
	build(rson,mid+1,r);
}

void del(int root,int pos,int val)
{
	del_val(rt[root],val);
	if(tr[root].l==tr[root].r)
	{
		return;
	}
	int mid=(tr[root].l+tr[root].r)>>1;
	if(pos<=mid) del(lson,pos,val);
	else del(rson,pos,val);
}

void update(int root,int pos,int val)
{
	insert(rt[root],val);
	if(tr[root].l==tr[root].r)
	{
		return;
	}
	int mid=(tr[root].l+tr[root].r)>>1;
	if(pos<=mid) update(lson,pos,val);
	else update(rson,pos,val);
}

int query(int root,int ll,int rr,int l,int r,int kk)
{
	if(ll==rr)
	{
		return tmp2[ll];
	}
	int sz=get_rk(rt[lson],r+1)-get_rk(rt[lson],l);
	int mid=(ll+rr)>>1;
	if(sz>=kk)
	{
		return query(lson,ll,mid,l,r,kk);
	}
	else
	{
		return query(rson,mid+1,rr,l,r,kk-sz);
	}
}

#undef lson
#undef rson

int main()
{
	freopen("1.in","r",stdin);
	freopen("1.ans","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		tmp2[++tot]=a[i];
	}
	for(int i=1;i<=m;i++)
	{
		scanf("%s",op);
		if(op[0]=='Q')
		{
			q[i].ll=read();
			q[i].rr=read();
			q[i].vv=read();
			q[i].kd=1;
		}
		else
		{
			if(op[0]=='C')
			{
				q[i].ll=read();
				q[i].vv=read();
				q[i].kd=2;
				tmp2[++tot]=q[i].vv;
			}
		}
	}
	init();
	build(1,1,tot);
	for(int i=1;i<=n;i++)
	{
		update(1,a[i],i);
	}
	for(int i=1;i<=m;i++)
	{
		if(q[i].kd==1)
		{
			printf("%d\n",query(1,1,tot,q[i].ll,q[i].rr,q[i].vv));
		}
		else
		{
			del(1,a[q[i].ll],q[i].ll);
			update(1,q[i].vv,q[i].ll);
			a[q[i].ll]=q[i].vv;
		}
	}
}

权值线段树

#include<bits/stdc++.h>
#define lson1 root<<1
#define rson1 root<<1|1
#define lson2 tr2[now].l
#define rson2 tr2[now].r
using namespace std;

int n,m,b[800020],a[800020],tot,rt[800020],tmp,cnt;

struct op
{
    int kd,l,r,val;
}p[800010];

struct tree1
{
    int l,r;
}tr1[800040];

struct tree2
{
    int l,r,sum;
}tr2[30000050];

inline int read()
{
    int f=1,x=0;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    return f*x;
}

void init()
{
    sort(b+1,b+cnt+1);
    tot=unique(b+1,b+cnt+1)-b-1;
    for(int i=1;i<=n;i++)
    {
        a[i]=lower_bound(b+1,b+tot+1,a[i])-b;
    }
    for(int i=1;i<=m;i++)
    {
        if(p[i].kd==2)
        {
            p[i].val=lower_bound(b+1,b+tot+1,p[i].val)-b;
        }
    }
}

//segment_tree2

void update2(int &now,int l,int r,int pos,int val)
{
    if(!now) now=++tmp;
    if(l==r)
    {
        tr2[now].sum+=val;
        return ;
    }
    register int mid=(l+r)>>1;
    if(pos<=mid)
    {
        update2(lson2,l,mid,pos,val);
    }
    else
    {
        update2(rson2,mid+1,r,pos,val);
    }
    tr2[now].sum=tr2[lson2].sum+tr2[rson2].sum;
}

int query2(int now,int l,int r,int ll,int rr)
{
    if(ll<=l&&r<=rr) return tr2[now].sum;
    register int mid=(l+r)>>1;
    if(rr<=mid)
    {
        return query2(lson2,l,mid,ll,rr);
    }
    else
    {
        if(ll>mid)
        {
            return query2(rson2,mid+1,r,ll,rr);
        }
        else
        {
            return query2(lson2,l,mid,ll,mid)+query2(rson2,mid+1,r,mid+1,rr);
        }
    }
}

//end

//segment_tree1

void build(int root,int l,int r)
{
    if(l==r) 
    {
        tr1[root].l=l;
        tr1[root].r=r;
        return ;
    }
    rt[root]=++tmp;
    tr1[root].l=l;
    tr1[root].r=r;
    int mid=(l+r)>>1;
    build(lson1,l,mid);
    build(rson1,mid+1,r);
}

void insert(int root,int pos,int val)
{
    if(tr1[root].l==tr1[root].r)
    {
        update2(rt[root],1,n,val,1);
        return ;
    }
    update2(rt[root],1,n,val,1);
    register int mid=(tr1[root].l+tr1[root].r)>>1;
    if(pos<=mid)
    {
        insert(lson1,pos,val);
    }
    else
    {
        insert(rson1,pos,val);
    }
}

void update(int root,int pos,int val)
{
    if(tr1[root].l==tr1[root].r)
    {
        update2(rt[root],1,n,val,1);
        return ;
    }
    update2(rt[root],1,n,val,1);
    register int mid=(tr1[root].l+tr1[root].r)>>1;
    if(pos<=mid)
    {
        update(lson1,pos,val);
    }
    else
    {
        update(rson1,pos,val);
    }
}

void del(int root,int pos,int val)
{
    if(tr1[root].l==tr1[root].r)
    {
        update2(rt[root],1,n,val,-1);
        return ;
    }
    update2(rt[root],1,n,val,-1);
    int mid=(tr1[root].l+tr1[root].r)>>1;
    if(pos<=mid)
    {
        del(lson1,pos,val);
    }
    else
    {
        del(rson1,pos,val);
    }
}

int query(int root,int l,int r,int gg)
{
    if(tr1[root].l==tr1[root].r)
    {
        return b[tr1[root].l];
    }
    int sz=query2(rt[lson1],1,n,l,r);
    if(sz>=gg)
    {
        return query(lson1,l,r,gg);
    }
    else
    {
        return query(rson1,l,r,gg-sz);
    }
}
//end

int main()
{
    scanf("%d%d",&n,&m);
    cnt=n;
    for(int i=1;i<=n;i++)
    {
        a[i]=read();
        b[i]=a[i];
    }
    char kd[10];
    for(int i=1;i<=m;i++)
    {
        scanf("%s",kd);
        if(kd[0]=='Q')
        {
            p[i].kd=1;
            p[i].l=read();
            p[i].r=read();
            p[i].val=read();
        }
        else
        {
            p[i].kd=2;
            p[i].l=read();
            p[i].val=read();
            b[++cnt]=p[i].val;
        }
    }
    init();
    build(1,1,tot);
//    printf("%d\n",tot);
    for(int i=1;i<=n;i++)
    {
//    	printf("%d %d\n",i,a[i]);
        insert(1,a[i],i);
    }
    int mag=0;
    for(int i=1;i<=m;i++)
    {
        if(p[i].kd==1)
        {
            printf("%d\n",query(1,p[i].l,p[i].r,p[i].val));
        }
        else
        {
            del(1,a[p[i].l],p[i].l);
            update(1,p[i].val,p[i].l);
            a[p[i].l]=p[i].val;
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值