再也不作死写FhqTreap作内层树了,卡的不如暴力呜呜呜……
题意翻译:给一个序列,每个下标包含两个属性$a$和$v$,求第一个属性与下标形成的所有逆序对的第二个属性和,给出$m$个交换两个下标的操作,每次操作之后查询。
考虑一下交换之后会发生什么:
假设这次要交换$x$和$y$,使$x leq y$。
发现交换之后$x, y$和$x$的左边的数和$y$右边的数构成的逆序对产生的贡献不变,发生变化的是中间的数。
那么问题就简单了,只要先消去中间的数和$x, y$的贡献,具体来说就是$[x + 1, y - 1]$这个区间中$a_{i}$比$a_{x}$小的$b_{i}$和,以及$a_{i}$比$a_{y}$大的$b_{i}$和。
发现$(x, y)$可能也会构成一个逆序对,拎出来判一下可以保证这一对只被计算一次。
然后算一下交换之后产生的贡献,方法类似。
树套树维护即可。
时间复杂度$O(nlog^{2}n)$。
Code:
#include <cstdio> #include <cstring> using namespace std; typedef long long ll; const int N = 5e4 + 5; const int M = 2e7 + 5; const ll P = 1e9 + 7; int n, m, a[N]; ll v[N], ans = 0LL; template <typename T> inline void read(T &X) { X = 0; char ch = 0; T op = 1; for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') op = -1; for(; ch >= '0' && ch <= '9'; ch = getchar()) X = (X << 3) + (X << 1) + ch - 48; X *= op; } template <typename T> inline void swap(T &x, T &y) { T t = x; x = y; y = t; } namespace BinaryIndexTree { int cnt[N]; ll s[N]; #define lowbit(x) (x & (-x)) inline void modifyS(int p, ll val) { for(; p <= n; p += lowbit(p)) s[p] = (s[p] + val) % P; } inline void modifyC(int p) { for(; p <= n; p += lowbit(p)) cnt[p]++; } inline ll getSum(int p) { ll res = 0; for(; p > 0; p -= lowbit(p)) res = (res + s[p]) % P; return res; } inline int getCnt(int p) { int res = 0; for(; p > 0; p -= lowbit(p)) res += cnt[p]; return res; } #undef lowbit } using namespace BinaryIndexTree; namespace Tree { int nodeCnt, root[N * 30]; struct Node { int lc, rc, siz; ll sum; } s[M]; #define mid ((l + r) >> 1) inline void up(int p) { if(!p) return; s[p].siz = s[s[p].lc].siz + s[s[p].rc].siz; s[p].sum = (s[s[p].lc].sum + s[s[p].rc].sum) % P; } void modify(int &p, int l, int r, int x, ll selV) { if(!p) p = ++nodeCnt; if(l == r) { s[p].siz = (selV != -1); s[p].sum = (selV == -1 ? 0 : selV % P); return; } if(x <= mid) modify(s[p].lc, l, mid, x, selV); else modify(s[p].rc, mid + 1, r, x, selV); up(p); } ll query(int p, int l, int r, int x, int y, ll selV) { if(!p) return 0LL; if(x <= l && y >= r) return (selV * s[p].siz % P + s[p].sum) % P; ll res = 0LL; if(x <= mid) res = (res + query(s[p].lc, l, mid, x, y, selV)) % P; if(y > mid) res = (res + query(s[p].rc, mid + 1, r, x, y, selV)) % P; return res; } #define lowbit(p) (p & (-p)) inline void change(int p, int val, ll selV) { for(; p <= n; p += lowbit(p)) modify(root[p], 1, n, val, selV); } inline void clear(int p, int val) { for(; p <= n; p += lowbit(p)) modify(root[p], 1, n, val, -1); } inline ll ask(int p, int v, ll selV, int type) { ll res = 0LL; for(; p > 0; p -= lowbit(p)) { if(type) res = (res + query(root[p], 1, n, v + 1, n, selV)) % P; else res = (res + query(root[p], 1, n, 1, v - 1, selV)) % P; } return res; } inline ll qSum(int l, int r, int v, ll selV, int type) { return (ask(r, v, selV, type) - ask(l - 1, v, selV, type) + P) % P; } } using namespace Tree; int main() { read(n), read(m); nodeCnt = 0; for(int i = 1; i <= n; i++) { read(a[i]), read(v[i]); ans = (ans + (getSum(n) - getSum(a[i]) + P) % P + P + v[i] * (getCnt(n) - getCnt(a[i])) % P + P) % P; modifyS(a[i], v[i]), modifyC(a[i]); change(i, a[i], v[i]); } for(int x, y; m--; ) { read(x), read(y); if(x == y) { printf("%lld ", ans); continue; } if(x > y) swap(x, y); ll res = 0LL; if(x + 1 <= y - 1) { res = (res + qSum(x + 1, y - 1, a[y], v[y], 1)) % P; res = (res + qSum(x + 1, y - 1, a[x], v[x], 0)) % P; } if(a[y] < a[x]) res = ((res + v[x]) % P + v[y]) % P; ans = (ans - res + P) % P; res = 0LL; if(x + 1 <= y - 1) { res = (res + qSum(x + 1, y - 1, a[y], v[y], 0)) % P; res = (res + qSum(x + 1, y - 1, a[x], v[x], 1)) % P; } if(a[y] > a[x]) res = ((res + v[x]) % P + v[y]) % P; ans = (ans + res) % P; printf("%lld ", ans); clear(x, a[x]), clear(y, a[y]); change(x, a[y], v[y]), change(y, a[x], v[x]); swap(a[x], a[y]), swap(v[x], v[y]); } return 0; }
// luogu-judger-enable-o2 #include <cstdio> #include <cstring> #include <cstdlib> using namespace std; typedef long long ll; const int N = 5e4 + 5; const int M = 2e7 + 5; const ll P = 1e9 + 7; int n, m, a[N]; ll v[N], ans = 0; namespace FhqTreap { int root[M], nodeCnt, ch[M][2], pri[M], siz[M]; ll key[M], sum[M], sel[M]; #define lc ch[p][0] #define rc ch[p][1] inline void up(int p) { if(p) { siz[p] = siz[lc] + siz[rc] + 1; sum[p] = (sum[lc] % P + sum[rc] % P + sel[p] % P) % P; } } inline int newnode(ll val, ll selV) { ++nodeCnt; key[nodeCnt] = val, sum[nodeCnt] = sel[nodeCnt] = selV; pri[nodeCnt] = rand(), siz[nodeCnt] = 1; return nodeCnt; } void split(int p, ll val, int &x, int &y) { if(!p) x = y = 0; else { if(val >= key[p]) x = p, split(rc, val, rc, y); else y = p, split(lc, val, x, lc); up(p); } } int merge(int x, int y) { if(!x || !y) return x + y; else { if(pri[x] < pri[y]) { ch[x][1] = merge(ch[x][1], y); up(x); return x; } else { ch[y][0] = merge(x, ch[y][0]); up(y); return y; } } } inline void insert(int rt, ll val, ll selV) { if(!root[rt]) { root[rt] = newnode(val, selV); return; } int x, y; split(root[rt], val, x, y); root[rt] = merge(x, merge(newnode(val, selV), y)); } inline void remove(int rt, ll val) { int x, y, z; split(root[rt], val, x, y); split(x, val - 1, x, z); z = merge(ch[z][0], ch[z][1]); root[rt] = merge(merge(x, z), y); } inline ll ask(int rt, ll val, ll selV, int type) { int x, y; ll res; if(type) { split(root[rt], val, x, y); res = (selV * siz[x] % P + sum[x]) % P; } else { split(root[rt], val, x, y); res = (selV * siz[y] % P + sum[y]) % P; } root[rt] = merge(x, y); return res % P; } void Pi(int p, int *arr) { if(lc) Pi(lc, arr); printf("%d ", arr[p]); if(rc) Pi(rc, arr); } #undef lc #undef rc }; namespace SegT { using namespace FhqTreap; #define lc p << 1 #define rc p << 1 | 1 #define mid ((l + r) >> 1) void ins(int p, int l, int r, int x, ll val, ll selV) { insert(p, val, selV); if(l == r) return; if(x <= mid) ins(lc, l, mid, x, val, selV); else ins(rc, mid + 1, r, x, val, selV); } void del(int p, int l, int r, int x, ll val) { remove(p, val); if(l == r) return; if(x <= mid) del(lc, l, mid, x, val); else del(rc, mid + 1, r, x, val); } ll query(int p, int l, int r, int x, int y, ll val, ll selV, int type) { if(x <= l && y >= r) return ask(p, val, selV, type) % P; ll res = 0; if(x <= mid) res = (res + query(lc, l, mid, x, y, val, selV, type)) % P; if(y > mid) res = (res + query(rc, mid + 1, r, x, y, val, selV, type)) % P; return res; } void print(int p, int l, int r, int *arr) { Pi(root[p], arr), printf(" "); if(l == r) return; print(lc, l, mid, arr), print(rc, mid + 1, r, arr); } } using namespace SegT; template <typename T> inline void swap(T &x, T &y) { T t = x; x = y; y = t; } namespace IOstream{ const int L = 1 << 15; char buffer[L], *S, *T; inline char Getchar() { if(S == T) { T = (S = buffer) + fread(buffer, 1, L, stdin); if(S == T) return EOF; } return *S++; } template <class T> inline void read(T &X) { char ch; T op = 1; for(ch = Getchar(); ch > '9' || ch < '0'; ch = Getchar()) if(ch == '-') op = -1; for(X = 0; ch >= '0' && ch <= '9'; ch = Getchar()) X = (X << 1) + (X << 3) + ch - '0'; X *= op; } template <typename T> inline void write(T x) { T sta[15]; int len = 0; if(x < 0) putchar('-'), x = -x; if(x == 0) { putchar('0'); return; } for(; x > 0; sta[++len] = x % 10, x /= 10); for(int i = len; i >= 1; i--) putchar(sta[i] + '0'); } } using namespace IOstream; namespace BinaryIndexTree { int cnt[N]; ll s[N]; #define lowbit(x) (x & (-x)) inline void modifyS(int p, ll val) { for(; p <= n; p += lowbit(p)) s[p] = (s[p] + val) % P; } inline void modifyC(int p) { for(; p <= n; p += lowbit(p)) cnt[p]++; } inline ll getSum(int p) { ll res = 0; for(; p > 0; p -= lowbit(p)) res = (res + s[p]) % P; return res; } inline int getCnt(int p) { int res = 0; for(; p > 0; p -= lowbit(p)) res += cnt[p]; return res; } } using namespace BinaryIndexTree; int main() { // freopen("1.in", "r", stdin); // freopen("mine.out", "w", stdout); // srand(19260817); read(n), read(m); nodeCnt = 0; for(int i = 1; i <= n; i++) { read(a[i]), read(v[i]); ans = (ans + (getSum(n) - getSum(a[i]) + P) % P + P + v[i] * (getCnt(n) - getCnt(a[i])) % P + P) % P; modifyS(a[i], v[i]), modifyC(a[i]); ins(1, 1, n, i, a[i], v[i]); } // printf("%d ", ans); for(int x, y; m--; ) { read(x), read(y); if(x == y) { printf("%lld ", ans); continue; } if(x > y) swap(x, y); ll res = 0; if(x + 1 <= y - 1) { res = (res + query(1, 1, n, x + 1, y - 1, a[y], v[y], 0)) % P; res = (res + query(1, 1, n, x + 1, y - 1, a[x], v[x], 1)) % P; } if(a[y] < a[x]) res = (res % P + v[x] % P + v[y] % P) % P; ans = (ans - res + P) % P; res = 0; if(x + 1 <= y - 1) { res = (res + query(1, 1, n, x + 1, y - 1, a[y], v[y], 1)) % P; res = (res + query(1, 1, n, x + 1, y - 1, a[x], v[x], 0)) % P; } if(a[y] > a[x]) res = (v[y] % P + v[x] % P + res % P) % P; ans = (ans + res) % P; write(ans), puts(""); del(1, 1, n, x, a[x]), del(1, 1, n, y, a[y]); ins(1, 1, n, y, a[x], v[x]), ins(1, 1, n, x, a[y], v[y]); swap(a[x], a[y]), swap(v[x], v[y]); /* print(1, 1, n, key), printf(" "); print(1, 1, n, sel), printf(" "); */ } return 0; }