[tyvj1730二逼平衡树]解题报告

学了一下主席树,由于怕调不出来,选择了用普通线段树套权值线段树。

犯得一些傻逼错误是:

①把大小写n混用结果弄错了。

②没过样例TM就交了。

③被题意坑了,“保证有序序列所有值在任何时刻满足[0,10^8]",并不意味着询问非负。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#include<iostream>
char * p=(char *)malloc(5000000);
inline int in(){
	int x=0;
	bool flag=0;
	while(*p<'0'||*p>'9')flag|=*p++=='-';
	while(*p>='0'&&*p<='9')x=x*10+*p++-'0';
	return flag?-x:x;
}
char buf[500000],* ptr=buf,tmp[10];
inline void out(int x){
	int tot=0;
	for(;x;x/=10)tmp[tot++]=x%10+'0';
	if(tot==0)*ptr++='0';
	else while(tot--)*ptr++=tmp[tot];
	*ptr++='\n';
}
 
int seq[50001],a[100001],N;
struct TS{
	int size,max,min;
	TS * c[2];
}root[200000],treepool[13000000],* list[40];
#define lson node<<1,l,(l+r)>>1
#define rson node<<1|1,((l+r)>>1)+1,r
int treetop=1,listtop;
int l[50000],r[50000],k[50000],opt[50000];
 
inline void add(TS * node,int l,int r,int A,int delta){
	node->size+=delta;
	if(l!=r){
		if(A>(l+r)>>1){
			if(node->c[1]==treepool){
				node->c[1]=treepool+treetop;
				treepool[treetop].c[0]=treepool[treetop].c[1]=treepool;
				treepool[treetop].max=-1,treepool[treetop].min=0x7fffffff;
				++treetop;
			}
			add(node->c[1],((l+r)>>1)+1,r,A,delta);
		}
		else{
			if(node->c[0]==treepool){
				node->c[0]=treepool+treetop;
				treepool[treetop].c[0]=treepool[treetop].c[1]=treepool;
				treepool[treetop].max=-1,treepool[treetop].min=0x7fffffff;
				++treetop;
			}
			add(node->c[0],l,(l+r)>>1,A,delta);
		}
		node->max=max(node->c[0]->max,node->c[1]->max);
		node->min=min(node->c[0]->min,node->c[1]->min);
	}
	else if(node->size)node->max=node->min=l;
	else node->max=-1,node->min=0x7fffffff;
}
inline int sum(TS * node,int l,int r,int A){
	if(l>=A||node->size==0)return 0;
	if(r<A)return node->size;
	return sum(node->c[0],l,(l+r)>>1,A)+sum(node->c[1],((l+r)>>1)+1,r,A);
}
inline int qk(int k){
	int suml,sumr,i,l=0,r=N-1;
	while(l!=r){
		suml=0,sumr=0;
		for(i=listtop;i--;)suml+=list[i]->c[0]->size,sumr+=list[i]->c[1]->size;
		if(suml>=k){
			for(i=listtop;i--;)list[i]=list[i]->c[0];
			r=(l+r)>>1;
		}
		else{
			for(i=listtop;i--;)list[i]=list[i]->c[1];
			l=((l+r)>>1)+1;
			k-=suml;
		}
	}
	return l;
}
inline int pred(TS * node,int l,int r,int A){
	if(l>=A||node->size==0)return -1;
	if(r<A)return node->max;
	return max(pred(node->c[0],l,(l+r)>>1,A),pred(node->c[1],((l+r)>>1)+1,r,A));
}
inline int succ(TS * node,int l,int r,int A){
	if(r<A||node->size==0)return 0x7fffffff;
	if(l>=A)return node->min;
	return min(succ(node->c[0],l,(l+r)>>1,A),succ(node->c[1],((l+r)>>1)+1,r,A));
}
 
 
inline void build(int node,int l,int r){
	if(l!=r)build(lson),build(rson);
	for(;l<=r;++l)add(root+node,0,N-1,seq[l],1);
}
inline int sum(int node,int l,int r,int L,int R,int A){
	if(l>R||r<L)return 0;
	if(L<=l&&r<=R)return sum(root+node,0,N-1,A);
	return sum(lson,L,R,A)+sum(rson,L,R,A);
}
inline void get(int node,int l,int r,int L,int R){
	if(L<=l&&r<=R){
		list[listtop++]=root+node;
		return;
	}
	if(R>(l+r)>>1)get(rson,L,R);
	if(L<=(l+r)>>1)get(lson,L,R);
}
inline void del(int node,int l,int r,int A){
	add(root+node,0,N-1,seq[A],-1);
	if(A>(l+r)>>1)del(rson,A);
	else if(l!=r)del(lson,A);
}
inline void add(int node,int l,int r,int A,int k){
	add(root+node,0,N-1,k,1);
	if(A>(l+r)>>1)add(rson,A,k);
	else if(l!=r)add(lson,A,k);
}
inline int pred(int node,int l,int r,int L,int R,int A){
	if(l>R||r<L)return -1;
	if(L<=l&&r<=R)return pred(root+node,0,N-1,A);
	return max(pred(lson,L,R,A),pred(rson,L,R,A));
}
inline int succ(int node,int l,int r,int L,int R,int A){
	if(l>R||r<L)return 0x7fffffff;
	if(L<=l&&r<=R)return succ(root+node,0,N-1,A);
	return min(succ(lson,L,R,A),succ(rson,L,R,A));
}
int main(){
	freopen("psh.in","r",stdin);
	freopen("psh.out","w",stdout);
	fread(p,1,5000000,stdin);
	int n=in(),m=in(),i,j;
	//Read,Sort,and Hash.
	for(i=1;i<=n;++i)seq[i]=in(),a[i-1]=seq[i];
	N=n;
	for(i=0;i<m;++i){
		opt[i]=in(),l[i]=in();
		if(opt[i]!=3)r[i]=in();
		k[i]=in();
		if(opt[i]==3)a[N++]=k[i];
	}
	sort(a,a+N);
	N=unique(a,a+N)-a;
	for(i=1;i<=n;++i)seq[i]=lower_bound(a,a+N,seq[i])-a;
	treepool->max=-1,treepool->min=0x7fffffff,treepool->c[0]=treepool->c[1]=treepool;
	for(i=0;i<200000;++i)root[i].max=-1,root[i].min=0x7fffffff,root[i].c[0]=root[i].c[1]=treepool;
	build(1,1,n);
	for(i=0;i<m;++i)
		switch(opt[i]){
			case 1:
				k[i]=lower_bound(a,a+N,k[i])-a;
				if(k[i])out(sum(1,1,n,l[i],r[i],k[i])+1);
				else out(1);
				break;
			case 2:
				listtop=0;
				get(1,1,n,l[i],r[i]);
				out(a[qk(k[i])]);
				break;
			case 3:
				k[i]=lower_bound(a,a+N,k[i])-a;
				del(1,1,n,l[i]);
				add(1,1,n,l[i],k[i]);
				seq[l[i]]=k[i];
				break;
			case 4:
				out(a[pred(1,1,n,l[i],r[i],lower_bound(a,a+N,k[i])-a)]);//<A
				break;
			case 5:
				out(a[succ(1,1,n,l[i],r[i],upper_bound(a,a+N,k[i])-a)]);//>=A
				break;
		}
	fwrite(buf,1,ptr-buf,stdout);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值