加上离散化为什么跑得更慢了?
查看原帖
加上离散化为什么跑得更慢了?
323849
kkksc03wzl楼主2024/2/26 01:49

这是在线算法的代码(树状数组套可持久化线段树)

#include<iostream>
#include<cstdio>
using namespace std;
struct node{int ls,rs,sum;}tr[45000004];
int tot=0;
int a[50005],n,rt[50005];
void upd(int &rt,int l,int r,int x,int k){
//	printf("%d %d %d\n",l,r,rt); 
//	if(tot>100*100004)cout<<tot<<endl;
	if(!rt)rt=++tot;
	tr[rt].sum+=k;
	if(l==r){return;}
	int mid=l+r>>1;
	if(x<=mid)upd(tr[rt].ls,l,mid,x,k);
	else upd(tr[rt].rs,mid+1,r,x,k);
}int lowbit(int x){return x&-x;}
void update(int pos,int x,int k){for(int i=pos; i<=n; i+=lowbit(i))upd(rt[i],0,100000000,x,k);}
int que(int rt,int l,int r,int x){
	if(r<=x){return tr[rt].sum;}
	int mid=l+r>>1;
	if(mid>=x){return que(tr[rt].ls,l,mid,x);}
	else {return tr[tr[rt].ls].sum+que(tr[rt].rs,mid+1,r,x);}
}int query(int pos,int x){int ans=0;for(int i=pos; i; i-=lowbit(i))ans+=que(rt[i],0,100000000,x);return ans;}
int find(int rt1[],int rt2[],int cnt1,int cnt2,int l,int r,int k){
	if(l==r){return l;}
	int sum=0;
	for(int i=1; i<=cnt1;i++)sum+=tr[tr[rt1[i]].ls].sum;
	for(int i=1; i<=cnt2;i++)sum-=tr[tr[rt2[i]].ls].sum;
	int mid=l+r>>1; 
	if(sum>=k){
		for(int i=1; i<=cnt1;i++)rt1[i]=tr[rt1[i]].ls;
		for(int i=1; i<=cnt2;i++)rt2[i]=tr[rt2[i]].ls;
		return find(rt1,rt2,cnt1,cnt2,l,mid,k);
	}else{
		for(int i=1; i<=cnt1;i++)rt1[i]=tr[rt1[i]].rs;
		for(int i=1; i<=cnt2;i++)rt2[i]=tr[rt2[i]].rs;
		return find(rt1,rt2,cnt1,cnt2,mid+1,r,k-sum);
	}
}int find_Kth(int l,int r,int k){
	int rt1[505],rt2[505],cnt1=0,cnt2=0;
	for(int i=r; i; i-=lowbit(i))rt1[++cnt1]=rt[i];
	for(int i=l-1;i;i-=lowbit(i))rt2[++cnt2]=rt[i];
//	cout<<rt[cnt1]<<" "<<cnt2<<endl;
	return find(rt1,rt2,cnt1,cnt2,0,100000000,k);
}
int main(){
// 	freopen("P3380_1.in","r",stdin);
// 	freopen("1919810.out","w",stdout); 
	int m;
	scanf("%d%d",&n,&m);
	for(int i=1; i<=n; i++){
		scanf("%d",&a[i]);
		update(i,a[i],1);
	}while(m--){
		int op,l,r,k;
		scanf("%d%d%d",&op,&l,&r);
		if(op==3){
			update(l,a[l],-1);
			a[l]=r;
			update(l,a[l],1);
		}else{
			scanf("%d",&k);
			if(op==1)printf("%d\n",query(r,k-1)-query(l-1,k-1)+1);
			else if(op==2)printf("%d\n",find_Kth(l,r,k));
			else if(op==4){
				int tmp=query(r,k-1)-query(l-1,k-1);
				if(tmp==0)printf("-2147483647\n");
				else printf("%d\n",find_Kth(l,r,tmp));
			}else{
				int tmp=query(r,k)-query(l-1,k)+1;
				if(tmp>r-l+1)printf("2147483647\n");
				else printf("%d\n",find_Kth(l,r,tmp));
			}
		}
	}
	return 0;
}

这是加上离散化以后的代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct node{int ls,rs,sum;}tr[45000004];
int tot=0;int num[1000005];
int a[50005],n,rt[50005];
void upd(int &rt,int l,int r,int x,int k){
	if(!rt)rt=++tot;
	tr[rt].sum+=k;
	if(l==r){return;}
	int mid=l+r>>1;
	if(x<=mid)upd(tr[rt].ls,l,mid,x,k);
	else upd(tr[rt].rs,mid+1,r,x,k);
}int lowbit(int x){return x&-x;}
void update(int pos,int x,int k){for(int i=pos; i<=n; i+=lowbit(i))upd(rt[i],1,num[0],x,k);}
int que(int rt,int l,int r,int x){
	if(r<=x){return tr[rt].sum;}
	int mid=l+r>>1;
	if(mid>=x){return que(tr[rt].ls,l,mid,x);}
	else {return tr[tr[rt].ls].sum+que(tr[rt].rs,mid+1,r,x);}
}int query(int pos,int x){int ans=0;for(int i=pos; i; i-=lowbit(i))ans+=que(rt[i],1,num[0],x);return ans;}
int find(int rt1[],int rt2[],int cnt1,int cnt2,int l,int r,int k){
	if(l==r){return l;}
	
	int sum=0;
	for(int i=1; i<=cnt1;i++)sum+=tr[tr[rt1[i]].ls].sum;
	for(int i=1; i<=cnt2;i++)sum-=tr[tr[rt2[i]].ls].sum;
	int mid=l+r>>1; 
//	cout<<l<<" "<<r<<" "<<sum<<" "<<k<<endl;
	if(sum>=k){
		for(int i=1; i<=cnt1;i++)rt1[i]=tr[rt1[i]].ls;
		for(int i=1; i<=cnt2;i++)rt2[i]=tr[rt2[i]].ls;
		return find(rt1,rt2,cnt1,cnt2,l,mid,k);
	}else{
		for(int i=1; i<=cnt1;i++)rt1[i]=tr[rt1[i]].rs;
		for(int i=1; i<=cnt2;i++)rt2[i]=tr[rt2[i]].rs;
		return find(rt1,rt2,cnt1,cnt2,mid+1,r,k-sum);
	}
}int find_Kth(int l,int r,int k){
	int rt1[505],rt2[505],cnt1=0,cnt2=0;
	for(int i=r; i; i-=lowbit(i))rt1[++cnt1]=rt[i];
	for(int i=l-1;i;i-=lowbit(i))rt2[++cnt2]=rt[i];
	return find(rt1,rt2,cnt1,cnt2,1,num[0],k);
}
struct que{int op,l,r,k;}b[100005];
int has(int x){return lower_bound(num+1,num+1+num[0],x)-num;}
int main(){
	int m;
	scanf("%d%d",&n,&m);
	for(int i=1; i<=n; i++){
		scanf("%d",&a[i]);
		num[++num[0]]=a[i];
//		update(i,a[i],1);
	}for(int i=1; i<=m; i++){
		int op,l,r,k;
		scanf("%d%d%d",&op,&l,&r);
		b[i].op=op,b[i].l=l,b[i].r=r;
		if(op!=3){
			scanf("%d",&k);
			b[i].k=k;
			if(op!=2)num[++num[0]]=k;
		}else num[++num[0]]=r;
//		if(op==3){
//			update(l,a[l],-1);
//			a[l]=r;
//			update(l,a[l],1);
//		}else{
//			scanf("%d",&k);
//			if(op==1)printf("%d\n",query(r,k-1)-query(l-1,k-1)+1);
//			else if(op==2)printf("%d\n",find_Kth(l,r,k));
//			else if(op==4){
//				int tmp=query(r,k-1)-query(l-1,k-1);
//				if(tmp==0)printf("-2147483647\n");
//				else printf("%d\n",find_Kth(l,r,tmp));
//			}else{
//				int tmp=query(r,k)-query(l-1,k)+1;
//				if(tmp>r-l+1)printf("2147483647\n");
//				else printf("%d\n",find_Kth(l,r,tmp));
//			}
//		}
	}sort(num+1,num+1+num[0]);
	num[0]=unique(num+1,num+1+num[0])-num-1;
//	cout<<num[0]<<endl;
	for(int i=1; i<=n; i++)a[i]=has(a[i]),update(i,a[i],1);
	for(int i=1; i<=m; i++){
		int op,l,r,k;
		op=b[i].op,l=b[i].l,r=b[i].r;
		if(op==3){
			r=has(r);
			update(l,a[l],-1);
			a[l]=r;
			update(l,a[l],1);
		}else{
			if(op==2){
				k=b[i].k;
//				cout<<l<<" "<<r<<endl;
				printf("%d\n",num[find_Kth(l,r,k)]);
//				cout<<"KTH"<<" "<<find_Kth(l,r,k)<<endl;
			}
			else{
				k=has(b[i].k);
				if(op==1)printf("%d\n",query(r,k-1)-query(l-1,k-1)+1);
				else if(op==4){
					int tmp=query(r,k-1)-query(l-1,k-1);
					if(tmp==0)printf("-2147483647\n");
					else printf("%d\n",num[find_Kth(l,r,tmp)]);
				}else{
					int tmp=query(r,k)-query(l-1,k)+1;
					if(tmp>r-l+1)printf("2147483647\n");
					else printf("%d\n",num[find_Kth(l,r,tmp)]);
				}
			}
		}
	}
	return 0;
}

有无佬哥帮助蒟蒻解释一下,是因为蒟蒻写得太弱了还是因为离散化就是更慢?

2024/2/26 01:49
加载中...