MnZn求助树套树
查看原帖
MnZn求助树套树
503792
Svemit楼主2024/4/24 12:59

rt,一个没过,每次输出的错误信息也不一样

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e4 + 5;
const int inf = 1 << 29;
const int mod = 1e9 + 7;

int n, m;
int ans;
int a[N], v[N];
struct Treap {
	int l, r, siz, dat, val, page;
	ll sum;
} tr[N << 5];

struct Node {
	ll sz, vsum;
};

Node operator + (const Node &lhs, const Node &rhs) {
	return (Node){lhs.sz + rhs.sz, lhs.vsum + rhs.vsum};
}

Node operator - (const Node &lhs, const Node &rhs) {
	return (Node){lhs.sz - rhs.sz, lhs.vsum - rhs.vsum};
}

int idx;
struct FHQ {
	void pushup(int x) {
		tr[x].siz = tr[tr[x].l].siz + tr[tr[x].r].siz + 1;
		tr[x].sum = tr[tr[x].l].sum + tr[tr[x].r].sum + tr[x].page;
	}

	int get_new(int val, int page) {
		tr[++ idx] = {0, 0, 1, rand(), val, page};
		return idx;
	}

	void split(int u, int val, int &x, int &y) {
		if (!u) x = y = 0;
		else {
			if (tr[u].val <= val) x = u, split(tr[u].r, val, tr[x].r, y);
			else y = u, split(tr[u].l, val, x, tr[y].l);
			pushup(u);
		}
	}

	int merge(int x, int y) {
		if (!x || !y) return x + y;
		if (tr[x].dat < tr[y].dat) {
			tr[x].r = merge(tr[x].r, y);
			pushup(x);
			return x;
		}
		else {
			tr[y].l = merge(x, tr[y].l);
			pushup(y);
			return y;
		}
	}

	void insert(int &rt, int val, int page) {
		int x, y;
		split(rt, val - 1, x, y);
		rt = merge(merge(x, get_new(val, page)), y);
	}

	void remove(int &rt, int val) {
		int x, y, z;
		split(rt, val, x, y), split(x, val - 1, x, z);
		z = merge(tr[z].l, tr[z].r);
		rt = merge(merge(x, z), y);
	}

	Node calc1(int &rt, int val) {
		int x, y;
		split(rt, val - 1, x, y);
		Node res = {tr[x].siz, tr[x].sum};
		rt = merge(x, y);
		return res;
	}

	Node calc2(int &rt, int val) {
		int x, y;
		split(rt, val, x, y);
		Node res = {tr[y].siz, tr[y].sum};
		rt = merge(x, y);
		return res;
	}
};

FHQ c[N];
int rt[N];

void ins(int x, int val, int page) {
	for (; x <= n; x += x & -x) c[x].insert(rt[x], val, page);
}

void del(int x, int val) {
	for (; x <= n; x += x & -x) c[x].remove(rt[x], val);
}

Node query1(int x, int val) {
	Node res = (Node){0, 0};
	for (; x; x -= x & -x) res = res + c[x].calc1(rt[x], val) - (Node){1, 0};
	return res;
}

Node query1(int l, int r, int val) {
	if (l > r) return (Node){0, 0};
	return query1(r, val) - query1(l - 1, val);
}

Node query2(int x, int val) {
	Node res = (Node){0, 0};
	for (; x; x -= x & -x) res = res + c[x].calc2(rt[x], val) - (Node){1, 0};
	return res;
}

Node query2(int l, int r, int val) {
	if (l > r) return (Node){0, 0};
	return query2(r, val) - query2(l - 1, val);
}

void add(ll &x, ll y) {
	x += y;
	if (x >= mod) x -= mod;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);
	srand(time(0));

	cin >> n >> m;
	for (int i = 1; i <= n; i ++) {
		c[i].insert(rt[i], inf, 0), c[i].insert(rt[i], -inf, 0);
	}

	ll ans = 0;
	for (int i = 1; i <= n; i ++) {
		cin >> a[i] >> v[i];
		ins(i, a[i], v[i]);
		Node t = query2(i - 1, a[i]);
		add(ans, t.vsum), add(ans, t.sz * v[i] % mod);
	}

	for (int i = 0; i < m; i ++) {
		int l, r;
		cin >> l >> r;
		if (l > r) swap(l, r);
		if (l != r) {
			Node t;
			t = query1(l + 1, r - 1, a[l]);
			add(ans, mod - t.vsum), add(ans, mod - t.sz * v[l] % mod);
			t = query2(l + 1, r - 1, a[l]);
			add(ans, t.vsum), add(ans, t.sz * v[l] % mod);
			t = query1(l + 1, r - 1, a[r]);
			add(ans, t.vsum), add(ans, t.sz * v[r] % mod);
			t = query2(l + 1, r - 1, a[r]);
			add(ans, mod - t.vsum), add(ans, mod - t.sz * v[r] % mod);
			if (a[r] > a[l]) add(ans, v[l] + v[r]);
			else add(ans, mod - v[l] - v[r]); 
			del(l, a[l]), del(r, a[r]);
			swap(a[l], a[r]), swap(v[l], v[r]);
			ins(l, a[l], v[l]), ins(r, a[r], v[r]);
		}
		cout << ans << "\n";
	}

	return 0;
}
2024/4/24 12:59
加载中...