BZOJ4889:[TJOI2017]不勤劳的图书管理员
浅谈树状数组与线段树:https://www.cnblogs.com/AKMer/p/9946944.html
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=4889
树状数组套线段树搞一搞就好了。
时间复杂度:\(O(nlog^2n)\)
空间复杂度:\(O(nlog^2n)\)
代码如下:
#include <cstdio>
#include <algorithm>
using namespace std;
typedef pair<int,int> pii;
#define low(i) ((i)&(-(i)))
#define fr first
#define sc second
const int maxn=5e4+5,pps=1e9+7;
int n,m,ans;
int pos[maxn],v[maxn];
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
struct segment_tree {
int tot;
pii tree[maxn*200];
int ls[maxn*200],rs[maxn*200];
void change(int p,int l,int r,int pos,int v,int cnt) {
while(1) {
tree[p].fr=(tree[p].fr+v)%pps;
tree[p].sc+=cnt;if(l==r)break;
int mid=(l+r)>>1;
if(pos<=mid) {
if(!ls[p])ls[p]=++tot;
r=mid,p=ls[p];
}
else {
if(!rs[p])rs[p]=++tot;
l=mid+1,p=rs[p];
}
}
}
}T;
struct TreeArray {
int cnt1,cnt2;
int rt[maxn],u1[maxn],u2[maxn];
void change(int pos,int key1,int key2,int cnt) {
for(int i=pos;i<=n;i+=low(i)) {
if(!rt[i])rt[i]=++T.tot;
T.change(rt[i],1,n,key1,key2,cnt);
}
}
int query(int L,int R,int pos,int val,int opt) {
if(R<=L)return 0;
cnt1=cnt2=0;pii res;res.fr=res.sc=0;
for(int i=L;i;i-=low(i))u1[++cnt1]=rt[i];
for(int i=R;i;i-=low(i))u2[++cnt2]=rt[i];
int l=1,r=n;
while(l!=r) {
int mid=(l+r)>>1;
if(pos<=mid) {
if(opt) {
for(int i=1;i<=cnt1;i++) {
int u=T.rs[u1[i]];
res.fr=(res.fr-T.tree[u].fr+pps)%pps;
res.sc=res.sc-T.tree[u].sc;
}
for(int i=1;i<=cnt2;i++) {
int u=T.rs[u2[i]];
res.fr=(res.fr+T.tree[u].fr)%pps;
res.sc=res.sc+T.tree[u].sc;
}
}
r=mid;
for(int i=1;i<=cnt1;i++)u1[i]=T.ls[u1[i]];
for(int i=1;i<=cnt2;i++)u2[i]=T.ls[u2[i]];
}
else {
if(!opt) {
for(int i=1;i<=cnt1;i++) {
int u=T.ls[u1[i]];
res.fr=(res.fr-T.tree[u].fr)%pps;
res.sc=res.sc-T.tree[u].sc;
}
for(int i=1;i<=cnt2;i++) {
int u=T.ls[u2[i]];
res.fr=(res.fr+T.tree[u].fr)%pps;
res.sc=res.sc+T.tree[u].sc;
}
}
l=mid+1;
for(int i=1;i<=cnt1;i++)u1[i]=T.rs[u1[i]];
for(int i=1;i<=cnt2;i++)u2[i]=T.rs[u2[i]];
}
}
return (res.fr+1ll*res.sc*val%pps)%pps;
}
}bit;
int main() {
n=read(),m=read();
for(int i=1;i<=n;i++) {
pos[i]=read(),v[i]=read();
ans=(ans+bit.query(0,i-1,pos[i],v[i],1))%pps;
bit.change(i,pos[i],v[i],1);
}
for(int i=1;i<=m;i++) {
int x=read(),y=read();
if(x>y)swap(x,y);
ans=(ans-bit.query(x,y-1,pos[y],v[y],1)+pps)%pps;
ans=(ans-bit.query(x,y-1,pos[x],v[x],0)+pps)%pps;
ans=(ans+bit.query(x,y-1,pos[y],v[y],0))%pps;
ans=(ans+bit.query(x,y-1,pos[x],v[x],1))%pps;
if(pos[x]>pos[y])ans=(ans-v[x]-v[y]+pps)%pps;
else if(pos[x]<pos[y])ans=(ans+v[x]+v[y])%pps;
bit.change(x,pos[x],-v[x],-1),bit.change(y,pos[y],-v[y],-1);
bit.change(x,pos[y],v[y],1),bit.change(y,pos[x],v[x],1);
swap(pos[x],pos[y]),swap(v[x],v[y]);
printf("%d\n",ans);
}
return 0;
}