P3157 [CQOI2011]动态逆序对 [树状数组套权值线段树]

传送门

发现每删除一个数, 对答案的贡献是前面大于它的和后面小于它的, 加上一个单点修改, 写一个树套数就可以了


#include<bits/stdc++.h>
#define N 100050
#define LL long long
using namespace std;
int read(){
	int cnt=0; char ch=0;
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))cnt=cnt*10+(ch-'0'),ch=getchar();
	return cnt;
}
int n,m,id[N],rt[N],tot; LL ans;
struct Node{int ls,rs,val;}t[N*400];
void Insert(int &x,int l,int r,int pos,int val){
	if(!x) x = ++tot; t[x].val+=val;
	if(l==r) return;
	int mid = (l+r) >> 1;
	if(pos<=mid) Insert(t[x].ls, l, mid, pos, val);
	else Insert(t[x].rs, mid+1, r, pos, val);
}
int Quary(int x,int l,int r,int L,int R){
	if(L<=l && r<=R) return (LL)t[x].val;
	int mid = (l+r) >> 1; LL ans = 0;
	if(L<=mid) ans += Quary(t[x].ls, l, mid, L, R);
	if(R>mid) ans += Quary(t[x].rs, mid+1, r, L, R);
	return ans;
}
void add(int x,int val,int k){for(;x<=n;x+=x&-x) Insert(rt[x],1,n,val,k);}
LL qu(int x,int L,int R){LL ans=0; for(;x;x-=x&-x) ans+=Quary(rt[x],1,n,L,R); return ans;}
LL Qu(int l,int r,int L,int R){if(l>r||L>R) return 0; return qu(r, L, R) - qu(l-1, L, R);}
int main(){
	n = read(); m = read();
	for(int i=1;i<=n;i++){
		int x = read(); id[x] = i;
		add(i,x,1); ans += Qu(1,i-1,x+1,n);
	}
	while(m--){
		printf("%lld\n",ans);
		int x = read(), pos = id[x];
		ans -= Qu(1,pos-1,x+1,n);
		ans -= Qu(pos+1,n,1,x-1);
		add(pos,x,-1);
	} return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FSYo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值