zoukankan      html  css  js  c++  java
  • 线段树 离散化 E. Infinite Inversions E. Physical Education Lessons

    题目一: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
    ", 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;
    }
    离散化+线段树
  • 相关阅读:
    C# 判断系统空闲(键盘、鼠标不操作一段时间)
    c#做动态(gif)中文验证码
    vue 移动端公众号采坑经验
    git常用命令汇总
    关于面试的相关问题
    jQuery请求后台接口
    谈谈前端行业一两点
    JQuery获取Dom元素的方法
    Vue--props
    函数的上下文就是函数里面的this是谁
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/11203957.html
Copyright © 2011-2022 走看看