题目一:E. Infinite Inversions
这个题目没什么思维量,还比较简单,就是离散化要加上每一个值的后面一个值,然后每一个值放进去的不是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\n", 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\n", 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\n", 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\n", 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\n", l);ans += query(1, l, len) * 1ll * num[i];update(1, l, num[i]);//printf("ans=%lld\n", ans); }printf("%lld\n", 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\n", i + 1, num[i + 1]); }//for (int i = 1; i <= len; i++) printf("i=%d %d\n",i, num[i]);build(1, 1, len);//printf("len=%d\n", 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\n", l, r);if (l > r) swap(l, r);update(1,1,len, l, r, k - 1);ll ans = tree[1].sum;printf("%lld\n", ans);}return 0; }