萌新求助动态逆序对的树状数组套动态开点线段树做法(0pt)
查看原帖
萌新求助动态逆序对的树状数组套动态开点线段树做法(0pt)
256970
xie_lzh楼主2022/7/28 14:45

rt,能过样例,但是0分

#include<bits/stdc++.h>
using namespace std;
int read()
{
	int r=0,f=1;
	char c=getchar();
	while(!isdigit(c))
	{
		if(c=='-') f=0;
		c=getchar();
	}
	while(isdigit(c))
	{
		r=(r<<1)+(r<<3)+c-48;
		c=getchar();
	}
	return f?r:-r;
}

const int N=1e5+5;
int n,m,tot,a[N],rt[N];
struct node
{
	int ls,rs,siz;
}tr[30000005];
void pushup(int p)
{
	tr[p].siz=tr[tr[p].ls].siz+tr[tr[p].rs].siz;
}
void update(int &p,int l,int r,int L,int val) // 动态开点 
{
	if(!p) p=++tot;
	if(l==r)
	{
		tr[p].siz+=val;
		return ;
	}
	int mid=(l+r)>>1;
	if(L<=mid) update(tr[p].ls,l,mid,L,val);
	else update(tr[p].rs,mid+1,r,L,val);
	pushup(p);
}
int lowbit(int x){return x&(-x);}
void ADD(int x,int k,int val) // 树状数组维护前缀和 
{
	while(x<=n)
	{
		update(rt[x],1,n,k,val);
		x+=lowbit(x);
	}
}
int q[2][30],cnt[2];
void prepare(int x,int y) // 将要询问的权值线段树插入序列 
{
	cnt[0]=cnt[1]=1;
	for(;x;x-=lowbit(x)) q[0][++cnt[0]]=rt[x];
	for(;y;y-=lowbit(y)) q[1][++cnt[1]]=rt[y];
}
int query1(int l,int r,int val) // 求区间内比val大的值的数量 
{
	if(l==r)return 0;
	int sum1=0,sum2=0,mid=(l+r)>>1;
	for(int i=1;i<=cnt[0];i++) sum1+=tr[tr[q[0][i]].rs].siz;
	for(int i=1;i<=cnt[1];i++) sum2+=tr[tr[q[1][i]].rs].siz;
	if(val>mid)
	{
		for(int i=1;i<=cnt[0];i++) q[0][i]=tr[q[0][i]].rs;
		for(int i=1;i<=cnt[1];i++) q[1][i]=tr[q[1][i]].rs;
		return query1(mid+1,r,val);
	} 
	else
	{
		for(int i=1;i<=cnt[0];i++) q[0][i]=tr[q[0][i]].ls;
		for(int i=1;i<=cnt[1];i++) q[1][i]=tr[q[1][i]].ls;
		return sum2-sum1+query1(l,mid,val);
	}
}
int query2(int l,int r,int val) // 求区间内比val小的值的数量 
{
	if(l==r)return 0;
	int sum1=0,sum2=0,mid=(l+r)>>1;
	for(int i=1;i<=cnt[0];i++) sum1+=tr[tr[q[0][i]].ls].siz;
	for(int i=1;i<=cnt[1];i++) sum2+=tr[tr[q[1][i]].ls].siz;
	if(val<=mid)
	{
		for(int i=1;i<=cnt[0];i++) q[0][i]=tr[q[0][i]].ls;
		for(int i=1;i<=cnt[1];i++) q[1][i]=tr[q[1][i]].ls;
		return query2(l,mid,val);
	}
	else
	{
		for(int i=1;i<=cnt[0];i++) q[0][i]=tr[q[0][i]].rs;
		for(int i=1;i<=cnt[1];i++) q[1][i]=tr[q[1][i]].rs;
		return sum2-sum1+query2(mid+1,r,val);
	}
}
int main()
{
	n=read(); m=read();
	for(int i=1;i<=n;i++)
	{
		a[i]=read();
		ADD(i,a[i],1);
	}
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		prepare(0,i-1);
		ans+=query1(1,n+1,a[i]);
	}
	while(m--)
	{
		cout<<ans<<endl;
		int x=read();
		prepare(0,x-1);
		ans-=query1(1,n,a[x]);
		prepare(x,n);
		ans-=query2(1,n,a[x]);
		ADD(x,a[x],-1);
	}
}
2022/7/28 14:45
加载中...