不勤劳的图书管理员

link

排队那道题的数据加强版,那道题是动态逆序对,这道题是动态带权逆序对,实际是差不多的。直接上线段树套动态开点线段树的板子就可以了,取模方面比较严格导致我的int写法一直没过,开龙龙宝宝就可以了。空间卡得比较死,甚至我用241M过掉的这道题(空间限制是250M,请叫我空间带师)。写法上注意两个权值的关系并正常更新答案即可。据说可以用指令集水过可能也是。。。

丑陋的代码:

#include<bits/stdc++.h>
//#define feyn
#define int long long
const int N=50010;
const int M=10000010;
const int mod=1e9+7;
using namespace std;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
    wh*=f;return;
}

int m,n,ans;
struct node{int pl,data;}a[N];
struct aa{int num,sum;};
inline aa operator +(aa s1,aa s2){return (aa){s1.num+s2.num,s1.sum+s2.sum};}

inline void swap(int &s1,int &s2){
	int s3=s1;s1=s2;s2=s3;return;
}
inline void swapn(node &s1,node &s2){
	node s3=s1;s1=s2;s2=s3;return;
}

namespace x{
	#define lc t[wh].left
	#define rc t[wh].right
	#define mid (l+r>>1)
	struct node{int left,right,num,sum;}newone,t[M];
	int cnt,top,st[M];
	inline int kk(){return top?st[top--]:++cnt;}
	inline void del(int wh){st[++top]=wh;t[wh]=newone;}
	
	inline void insert(int &wh,int l,int r,int pl,int val){
		if(!wh)wh=kk();t[wh].num++,t[wh].sum+=val;
		if(l==r)return;
		if(pl<=mid)insert(lc,l,mid,pl,val);
		else insert(rc,mid+1,r,pl,val);
	}
	inline void delet(int &wh,int l,int r,int pl,int val){
		t[wh].num--,t[wh].sum-=val;
		if(l^r){
			if(pl<=mid)delet(lc,l,mid,pl,val);
			else delet(rc,mid+1,r,pl,val);
		}
		if(t[wh].num==0)del(wh),wh=0;return;
	}
	inline aa work(int wh,int l,int r,int wl,int wr){
		if(!wh)return (aa){0,0};
		if(wl<=l&&r<=wr)return (aa){t[wh].num,t[wh].sum};
		aa an=(aa){0,0};
		if(wl<=mid)an=an+work(lc,l,mid,wl,wr);
		if(wr>mid)an=an+work(rc,mid+1,r,wl,wr);
		return an;
	}
	int rt[N<<2];
	inline void solve(int wh,int bef,int aft){
		if(aft==0)insert(rt[wh],1,m,a[bef].pl,a[bef].data);
		else{
			delet(rt[wh],1,m,a[bef].pl,a[bef].data);
			insert(rt[wh],1,m,a[aft].pl,a[aft].data);
		}
	}
	#undef lc
	#undef rc
	#undef mid
}

namespace y{
	#define lc (wh<<1)
	#define rc (wh<<1|1)
	#define mid (t[wh].l+t[wh].r>>1)
	struct node{
		int l,r;
	}t[N<<2];
	void build(int wh,int l,int r){
		t[wh].l=l,t[wh].r=r;
		if(l==r)return;
		build(lc,l,mid);
		build(rc,mid+1,r);
	}
	inline void change(int wh,int pl,int ft){
		if(pl==ft)return;
		x::solve(wh,pl,ft);
		if(t[wh].l==t[wh].r)return;
		change(pl<=mid?lc:rc,pl,ft);
	}
	inline aa work(int wh,int wl,int wr,int ql,int qr){
		if(wl>wr||ql>qr)return (aa){0,0};
		if(wl<=t[wh].l&&t[wh].r<=wr){
			return x::work(x::rt[wh],1,m,ql,qr);
		}
		aa an=(aa){0,0};
		if(wl<=mid)an=an+work(lc,wl,wr,ql,qr);
		if(wr>mid)an=an+work(rc,wl,wr,ql,qr);
		return an;
	}
	#undef lc
	#undef rc
	#undef mid
}

namespace z{
	#define lowbit (wh&-wh)
	aa t[N];
	inline void change(int wh,int val){
		for(;wh<=m;wh+=lowbit)t[wh]=t[wh]+(aa){1,val};
	}
	inline aa work(int wh){
		aa an={0,0};
		for(;wh;wh-=lowbit)an=an+t[wh];
		return an;
	}
	#undef lowbit
}

signed main(){
	
	#ifdef feyn
	freopen("in.txt","r",stdin);
	#endif
	
	read(m);read(n);int sum=0;aa an;
	for(int i=1;i<=m;i++){
		read(a[i].pl);read(a[i].data);
		an=z::work(a[i].pl);
		ans+=(sum-an.sum)+(i-1-an.num)*a[i].data;
		z::change(a[i].pl,a[i].data);
		sum+=a[i].data;
	}
	y::build(1,1,m);
	for(int i=1;i<=m;i++){
		y::change(1,i,0);
	}
	int s1,s2;
	while(n--){
		read(s1);read(s2);
		if(s1>s2)swap(s1,s2);
		
		an=y::work(1,s1+1,s2-1,a[s1].pl+1,m);
		ans+=an.sum+an.num*a[s1].data;
		an=y::work(1,s1+1,s2-1,1,a[s1].pl-1);
		ans-=an.sum+an.num*a[s1].data;
		an=y::work(1,s1+1,s2-1,a[s2].pl+1,m);
		ans-=an.sum+an.num*a[s2].data;
		an=y::work(1,s1+1,s2-1,1,a[s2].pl-1);
		ans+=an.sum+an.num*a[s2].data;
		
		y::change(1,s1,s2);
		y::change(1,s2,s1);
		if(a[s1].pl>a[s2].pl)ans-=a[s1].data+a[s2].data;
		if(a[s2].pl>a[s1].pl)ans+=a[s1].data+a[s2].data;
		swapn(a[s1],a[s2]);
		printf("%lld\n",ans%mod);
	}
	
	return 0;
}
posted @ 2022-07-24 21:15  Feyn618  阅读(15)  评论(0编辑  收藏  举报