洛谷P3759 [TJOI2017]不勤劳的图书管理员 【树状数组套主席树】

题目链接

洛谷P3759

题解

树状数组套主席树板题

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
#define lbt(x) (x & -x)
using namespace std;
const int maxn = 100005,maxm = 10000005,INF = 1000000000,P = 1000000007;
inline int read(){
	int out = 0,flag = 1; char c = getchar();
	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
	return out * flag;
}
int sum[maxm],siz[maxm],ls[maxm],rs[maxm],cnt;
void upd(int u){
	sum[u] = (sum[ls[u]] + sum[rs[u]]) % P;
	siz[u] = siz[ls[u]] + siz[rs[u]];
}
void Modify(int& u,int l,int r,int pos,int v,int vv){
	if (!u) u = ++cnt;
	if (l == r){sum[u] += v; siz[u] += vv; return;}
	int mid = l + r >> 1;
	if (mid >= pos) Modify(ls[u],l,mid,pos,v,vv);
	else Modify(rs[u],mid + 1,r,pos,v,vv);
	upd(u);
}
cp Query(int u,int l,int r,int L,int R){
	if (!u) return mp(0,0);
	if (l >= L && r <= R) return mp(sum[u],siz[u]);
	int mid = l + r >> 1;
	if (mid >= R) return Query(ls[u],l,mid,L,R);
	if (mid < L) return Query(rs[u],mid + 1,r,L,R);
	cp t = Query(ls[u],l,mid,L,R),tt = Query(rs[u],mid + 1,r,L,R);
	return mp((t.first + tt.first) % P,t.second + tt.second);
}
int rt[maxn << 2],n,m,N = 100005,A[maxn],V[maxn]; LL ans;
void modify(int u,int pos,int v,int vv){
	for (int i = u; i <= N; i += lbt(i))
		Modify(rt[i],1,N,pos,v,vv);
}
cp query(int l,int r,int L,int R){
	if (L > R) return mp(0,0);
	cp re = mp(0,0),t;
	for (int i = r; i; i -= lbt(i)){
		t = Query(rt[i],1,N,L,R);
		re.first = (re.first + t.first) % P;
		re.second += t.second;
	}
	for (int i = l - 1; i; i -= lbt(i)){
		t = Query(rt[i],1,N,L,R);
		re.first = (re.first - t.first + P) % P;
		re.second -= t.second;
	}
	return re;
}
int main(){
	n = read(); m = read();
	int x,y; cp t,tt;
	REP(i,n){
		A[i] = read(); V[i] = read();
		if (i - 1){
			t = query(1,i - 1,A[i] + 1,N);
			ans = ((ans + t.first) % P + 1ll * t.second * V[i] % P) % P;
		}
		modify(i,A[i],V[i],1);
	}
	while (m--){
		x = read(); y = read();
		if (x == y){printf("%lld\n",(ans % P + P) % P); continue;}
		if (x > y) swap(x,y);
		if (A[x] < A[y]) ans = ((ans + V[x]) % P + V[y]) % P;
		else ans = ((ans - (V[x] + V[y]) % P) % P + P) % P;
		if (x < y){
			t = query(x + 1,y - 1,A[x] + 1,N);
			tt = query(x + 1,y - 1,1,A[x] - 1);
			t.first = (t.first - tt.first) % P; t.second -= tt.second;
			ans = ((ans + t.first) % P + 1ll * V[x] * t.second % P) % P;
			t = query(x + 1,y - 1,1,A[y] - 1);
			tt = query(x + 1,y - 1,A[y] + 1,N);
			t.first = ((t.first - tt.first) % P + P) % P; t.second -= tt.second;
			ans = ((ans + t.first) % P + 1ll * V[y] * t.second % P) % P;
		}
		modify(x,A[x],-V[x],-1);
		modify(y,A[y],-V[y],-1);
		modify(x,A[y],V[y],1);
		modify(y,A[x],V[x],1);
		swap(A[x],A[y]); swap(V[x],V[y]);
		printf("%lld\n",(ans % P + P) % P);
	}
	return 0;
}

posted @ 2018-05-30 08:52  Mychael  阅读(236)  评论(0编辑  收藏  举报