这个题目没什么思维量,还比较简单,就是离散化要加上每一个值的后面一个值,然后每一个值放进去的不是1 ,而是这个值与下一个点的差值。
因为这个数代表了一堆数,然后每一次的找到了的逆序对都要乘以这个num。
#include <cstdio> #include <cstdlib> #include <cstring> #include <queue> #include <vector> #include <algorithm> #include <string> #include <iostream> #include <map> #define inf 0x3f3f3f3f #define inf64 0x3f3f3f3f3f3f3f3f using namespace std; const int maxn = 4e5 + 10; typedef long long ll; int num[maxn], a[maxn], b[maxn]; pair<ll, ll>ex[maxn]; struct node { int l, r; int num; }tree[4 * maxn]; void build(int id, int l, int r) { tree[id].l = l; tree[id].r = r; if (l == r) { tree[id].num = 0; return; } int mid = (l + r) >> 1; build(id << 1, l, mid); build(id << 1 | 1, mid + 1, r); } int query(int id, int x, int y) { int l = tree[id].l; int r = tree[id].r; if (x <= l && y >= r) { return tree[id].num; } int ans = 0; int mid = (l + r) >> 1; if (x <= mid) ans += query(id << 1, x, y); if (y > mid) ans += query(id << 1 | 1, x, y); return ans; } void push_up(int id) { tree[id].num =tree[id << 1].num+tree[id << 1 | 1].num; } void update(int id, int x, int val) { int l = tree[id].l; int r = tree[id].r; if (l == r) { //printf("id=%d x=%d val=%d ", id, x, val); tree[id].num = val; return; } int mid = (l + r) >> 1; if (x <= mid) update(id << 1, x, val); else update(id << 1 | 1, x, val); push_up(id); } int main() { int n, tot = 0; scanf("%d", &n); for (int i = 1; i <= n; i++) { int u, v; scanf("%d%d", &u, &v); ex[i] = make_pair(u, v); a[tot++] = u, a[tot++] = v; a[tot++] = u + 1, a[tot++] = v + 1; } sort(a, a + tot); int len = unique(a, a + tot) - a; //printf("len=%d ", len); num[len - 1] = 1; for (int i = 0; i < len - 1; i++) { num[i] = a[i + 1] - a[i]; //printf("num[%d]=%d a[%d]=%d ", i, num[i], i, a[i]); } memcpy(b, a, sizeof(a)); for(int i=1;i<=n;i++) { ex[i].first = lower_bound(a, a + len, ex[i].first) - a; ex[i].second = lower_bound(a, a + len, ex[i].second) - a; //printf("ex[%d] %lld %lld ", i, ex[i].first, ex[i].second); } for (int i = 1; i <= n; i++) swap(a[ex[i].first], a[ex[i].second]), swap(num[ex[i].first], num[ex[i].second]); ll ans = 0; build(1, 1, len); for(int i=0;i<len;i++) { int l = lower_bound(b, b + len, a[i]) - b + 1; //printf("l=%d ", l); ans += query(1, l, len) * 1ll * num[i]; update(1, l, num[i]); //printf("ans=%lld ", ans); } printf("%lld ", ans); return 0; }
今天20190809来补一下这个题目的树状数组,一直都没有学过树状数组,今天浅显的学习了一下,学习网站https://www.cnblogs.com/xenny/p/9739600.html
这个讲的还是很详细也很容易理解。
这个还是照着上面的思路,只是把线段树换成树状数组。
今天感觉自己傻了,这个树状数组容易写,但是下面的这个离散化写搓了,这个num数组应该记录的是这个数带这五个数的后面一位有多少个
而不可以是这个数和这个数的前面一位之间有多少个,因为这个比这个数小的肯定比大于这个数的数小,所以肯定是可以构成逆序对的。
#include <cstdio> #include <cstdlib> #include <cstring> #include <queue> #include <vector> #include <string> #include <algorithm> #include <iostream> #include <map> #define inf 0x3f3f3f3f #define inf64 0x3f3f3f3f3f3f3f3f using namespace std; typedef long long ll; const int maxn = 4e5 + 10; int n; ll c[maxn]; //对应原数组和树状数组 int lowbit(int x) { return x & (-x); } void updata(int i, ll k) { //在i位置加上k while (i <= n) { c[i] += k; i += lowbit(i); } } ll getsum(int i) { //求A[1 - i]的和 ll res = 0; while (i > 0) { res += c[i]; i -= lowbit(i); } return res; } ll num[maxn]; ll b[maxn], a[maxn]; struct node { int l, r; node(int l = 0, int r = 0) :l(l), r(r) {} }ex[maxn]; int main() { int m, tot = 0; scanf("%d", &m); for (int i = 1; i <= m; i++) { int l, r; scanf("%d%d", &l, &r); ex[i] = node(l, r); b[++tot] = l; b[++tot] = l + 1; b[++tot] = r; b[++tot] = r + 1; } sort(b + 1, b + 1 + tot); n = unique(b + 1, b + 1 + tot) - b - 1; num[n] = 1; for (int i = 1; i < n; i++) { num[i] = b[i + 1] - b[i]; } memcpy(a, b, sizeof(b)); for (int i = 1; i <= m; i++) { ex[i].l = lower_bound(b + 1, b + 1 + n, ex[i].l) - b; ex[i].r = lower_bound(b + 1, b + 1 + n, ex[i].r) - b; } for (int i = 1; i <= m; i++) { swap(a[ex[i].l], a[ex[i].r]), swap(num[ex[i].l], num[ex[i].r]); } ll ans = 0; for (int i = 1; i <= n; i++) { int l = lower_bound(b + 1, b + 1 + n, a[i]) - b; ll res = getsum(n) - getsum(l); ans += res * num[i]; updata(l, num[i]); } printf("%lld ", ans); return 0; }
题目二:E. Physical Education Lessons
这个空间开的特别变态,空间要开的很大,而且这个空间给的也不是很多,没什么思维量,比较简单。
开始在第17发 re到我怀疑我写搓了,然后就是第一发mle。。。
#include <cstdio> #include <cstdlib> #include <cstring> #include <queue> #include <vector> #include <algorithm> #include <string> #include <iostream> #include <map> #define inf 0x3f3f3f3f #define inf64 0x3f3f3f3f3f3f3f3f using namespace std; const int maxn1 = 1e7 + 5e6 + 10; const int maxn = 3e5 + 10; typedef long long ll; int a[maxn * 4], num[maxn1]; struct edge { int u, v, opt; edge(int u = 0, int v = 0, int opt = 0) :u(u), v(v), opt(opt) {} }order[maxn * 2]; struct node { int lazy; int sum, num; }tree[maxn1]; void push_up(int id) { tree[id].sum = tree[id << 1].sum + tree[id << 1 | 1].sum; tree[id].num = tree[id << 1].num + tree[id << 1 | 1].num; } void build(int id, int l, int r) { tree[id].lazy = -1; if (l == r) { tree[id].sum = num[l]; tree[id].num = num[l]; return; } int mid = (l + r) >> 1; build(id << 1, l, mid); build(id << 1 | 1, mid + 1, r); push_up(id); } void push_down(int id) { if (tree[id].lazy != -1) { tree[id << 1].sum = tree[id << 1].num*tree[id].lazy; tree[id << 1 | 1].sum = tree[id << 1 | 1].num*tree[id].lazy; tree[id << 1].lazy = tree[id].lazy; tree[id << 1 | 1].lazy = tree[id].lazy; tree[id].lazy = -1; } } void update(int id,int l,int r, int x, int y, int k) { push_down(id); if (x <= l && y >= r) { tree[id].lazy = k; tree[id].sum = tree[id].num*k; return; } int mid = (l + r) >> 1; if (x <= mid) update(id << 1, l, mid, x, y, k); if (y > mid) update(id << 1 | 1, mid + 1, r, x, y, k); push_up(id); } int main() { int n, m, tot = 1; scanf("%d%d", &n, &m); a[0] = 1; for (int i = 1; i <= m; i++) { int u, v, k; scanf("%d%d%d", &u, &v, &k); order[i] = edge(u, v, k); a[tot++] = u, a[tot++] = u + 1; a[tot++] = v, a[tot++] = v + 1; } sort(a, a + tot); int len = unique(a, a + tot) - a; for (int i = 1; i <= m; i++) { order[i].u = lower_bound(a, a + len, order[i].u) - a + 1; order[i].v = lower_bound(a, a + len, order[i].v) - a + 1; } num[len] = n - a[len - 1] + 1; for (int i = 0; i < len - 1; i++) { num[i + 1] = a[i + 1] - a[i]; //printf("num[%d]=%d ", i + 1, num[i + 1]); } //for (int i = 1; i <= len; i++) printf("i=%d %d ",i, num[i]); build(1, 1, len); //printf("len=%d ", len); for (int i = 1; i <= m; i++) { int l = order[i].u; int r = order[i].v; int k = order[i].opt; //printf("l=%d r=%d ", l, r); if (l > r) swap(l, r); update(1,1,len, l, r, k - 1); ll ans = tree[1].sum; printf("%lld ", ans); } return 0; }