有 (n) 个元素构成的序列,每个元素有属性 (a[i],v[i]),有 (m) 次操作,每次给定 (x,y),交换这两个元素的位置。你需要在每次操作后输出序列的混乱度。如果 (i<j and a[i]>a[j]) 就会贡献 (v[i]+v[j]) 的混乱度。
Solution
丢到二维平面上,(x) 表示顺序,(y) 表示 (a),外层普通线段树,内层权值线段树,维护和即可
需要垃圾回收,日常卡常
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 100005;
const int M = 1.5e7;
const int mod = 1e+9+7;
int n,m,a[N],v[N],ans;
inline int prot(int x) {
if(x>mod) return x-mod;
return x;
}
struct node {
int sum; signed cnt;
node operator + (const node &b) const {
return {prot(this->sum+b.sum), prot(this->cnt+b.cnt)};
}
bool empty() {
return sum==0 && cnt==0;
}
};
namespace iseg {
node tr[M]; signed ch[M][2];
signed s[M+1], top;
void init() {
for(int i=1;i<M;i++) s[++top]=i;
}
int newnode() {
signed tmp=s[top--];
return tmp;
}
void modify(int p,int l,int r,int pos,node val) {
tr[p]=tr[p]+val;
if(l<r) {
if(pos<=(l+r)/2) {
if(ch[p][0]==0) ch[p][0]=newnode();
modify(ch[p][0],l,(l+r)/2,pos,val);
if(tr[ch[p][0]].empty()) {
s[++top]=ch[p][0];
ch[p][0]=0;
}
}
else {
if(ch[p][1]==0) ch[p][1]=newnode();
modify(ch[p][1],(l+r)/2+1,r,pos,val);
if(tr[ch[p][1]].empty()) {
s[++top]=ch[p][1];
ch[p][1]=0;
}
}
}
}
node query(int p,int l,int r,int ql,int qr) {
if(l>qr||r<ql||!p) return {0,0};
if(l>=ql&&r<=qr) return tr[p];
return query(ch[p][0],l,(l+r)/2,ql,qr)+query(ch[p][1],(l+r)/2+1,r,ql,qr);
}
}
namespace oseg {
int tr[N*4];
void modify(int p,int l,int r,int x,int y,node v) {
if(tr[p]==0) tr[p]=iseg::newnode();
iseg::modify(tr[p],1,n,y,v);
if(l<r) {
if(x<=(l+r)/2) modify(p*2,l,(l+r)/2,x,y,v);
else modify(p*2+1,(l+r)/2+1,r,x,y,v);
}
}
void modify(int x,int y,node v) {
modify(1,1,n,x,y,v);
}
node query(int p,int l,int r,int ql,int qr,int vl,int vr) {
if(l>qr||r<ql) return {0,0};
if(l>=ql&&r<=qr) return iseg::query(tr[p],1,n,vl,vr);
return query(p*2,l,(l+r)/2,ql,qr,vl,vr)+query(p*2+1,(l+r)/2+1,r,ql,qr,vl,vr);
}
node query(int ql,int qr,int vl,int vr) {
return query(1,1,n,ql,qr,vl,vr);
}
}
void modify(int x,int y,node v) {
oseg::modify(x,y,v);
}
node query(int ql,int qr,int vl,int vr) {
return oseg::query(ql,qr,vl,vr);
}
int calc(int i,int l,int r) {
node tmp = query(i+1,r,1,a[i]-1) + query(l,i-1,a[i]+1,n);
//cout<<"calc "<<i<<" "<<tmp.cnt<<","<<tmp.sum<<endl;
return (tmp.cnt*v[i]+tmp.sum)%mod;
}
signed main() {
ios::sync_with_stdio(false);
iseg::init();
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i]>>v[i];
for(int i=1;i<=n;i++) {
modify(i,a[i],{v[i],1});
ans+=calc(i,1,n);
}
for(int i=1;i<=m;i++) {
int x,y;
cin>>x>>y;
ans-=calc(x,min(x,y),max(x,y));
modify(x,a[x],{-v[x],-1});
ans-=calc(y,min(x,y),max(x,y));
modify(y,a[y],{-v[y],-1});
swap(a[x],a[y]);
swap(v[x],v[y]);
modify(x,a[x],{v[x],1});
ans+=calc(x,min(x,y),max(x,y));
modify(y,a[y],{v[y],1});
ans+=calc(y,min(x,y),max(x,y));
cout<<ans%mod<<endl;
}
}