zoukankan      html  css  js  c++  java
  • bzoj4889

    http://www.lydsy.com/JudgeOnline/problem.php?id=4889

    人傻常数大 bzoj上跑不过 洛谷上能过两到三个点

    我写的是树套树啊 怎么跑的比分块还慢

    每次可以发现交换两个点 只对他们中间的点有影响 所以我们只用计算比x小的数的和 比x大的数的和 比y小的数的和 比y大的数的和 然后计算一下就可以了 很明显可以用各种数据结构维护

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 4000010;
    const ll mod = 1000000007;
    int n, m, cnt;
    ll ans;
    int q[N];
    inline int read()
    {
        int x = 0, f = 1; char c = getchar();
        while(c < '0' || c > '9')
        {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9')
        {
            x = x * 10 + c - '0';
            c = getchar();
        }
        return x * f;
    }
    struct BIT {
        ll tree[N], count[N];
        int lowbit(int i) 
        {
            return i & (-i);
        }
        void update(int pos, ll delta)
        {    
            for(int i = pos; i <= 50001; i += lowbit(i))
            { 
                tree[i] = (tree[i] + delta) % mod;
                ++count[i];
            }
        }
        ll query(int pos, ll delta)
        {
            ll ret1 = 0, ret2 = 0;
            for(int i = pos; i; i -= lowbit(i))
            { 
                ret1 = (ret1 + tree[i]) % mod;
                ret2 += count[i];
            }
            ret1 = (ret1 + ret2 * delta) % mod; 
            return ret1;    
        }
    } B;
    struct data {
        int a;
        ll v;
    } tree[N], a[N];
    namespace splaytree
    {
        int fa[N], child[N][2], root[N];
        ll size[N], num[N], sum[N];
        void update(int x)
        {
            size[x] = num[x] + size[child[x][0]] + size[child[x][1]];
            sum[x] = (tree[x].v * num[x] + sum[child[x][0]] + sum[child[x][1]]) % mod;
        }
        void zig(int x)
        {
            int y = fa[x];
            fa[x] = fa[y]; 
            child[fa[x]][child[fa[x]][1] == y] = x;
            child[y][0] = child[x][1];
            fa[child[x][1]] = y;
            fa[y] = x;
            child[x][1] = y;
            update(y); 
            update(x);        
        }
        void zag(int x)
        {
            int y = fa[x];
            fa[x] = fa[y]; 
            child[fa[x]][child[fa[x]][1] == y] = x;
            child[y][1] = child[x][0];
            fa[child[x][0]] = y;
            fa[y] = x;
            child[x][0] = y;
            update(y); 
            update(x);        
        }
        void splay(int x, int t, int pos)
        {
            while(fa[x] != t)
            {
                int y = fa[x], z = fa[y];
                if(z == t)
                {
                    child[y][0] == x ? zig(x) : zag(x); 
                    break;
                }
                else if(y == child[z][0] && x == child[y][0]) { zig(y); zig(x); }
                else if(y == child[z][1] && x == child[y][1]) { zag(y); zag(x); }
                else if(y == child[z][0] && x == child[y][1]) { zag(x); zig(x); }
                else if(y == child[z][1] && x == child[y][0]) { zig(x); zag(x); }
            }
            if(!t) root[pos] = x;
            update(root[pos]);
        }
        void up(int x)
        {
            while(x)
            {
                update(x);
                x = fa[x];
            }
        }
        ll getbig(int pos, data &k)
        {
            int now = root[pos];
            ll ret = 0;
            while(now)
            {
                if(tree[now].a > k.a) 
                {
                    ret = (ret + k.v + tree[now].v) % mod;            
                    ret = (ret + k.v * size[child[now][1]] +
                           sum[child[now][1]]) % mod;
                    now = child[now][0];
                }
                else now = child[now][1];
            }
            return ret;
        }
        ll getsmall(int pos, data &k)
        {
            int now = root[pos];
            ll ret = 0;
            while(now)
            {
                if(tree[now].a < k.a)
                { 
                    ret = (ret + k.v + tree[now].v) % mod;
                    ret = (ret + k.v * size[child[now][0]] +
                           sum[child[now][0]]) % mod;
                    now = child[now][1];
                }
                else now = child[now][0];
            }
            return ret;
        }
        int find(int x, data &k)
        {
            for(x = root[x]; x; x = child[x][k.a > tree[x].a])
                if(tree[x].a == k.a) return x;
        }
        void del(int pos, int x)
        {
            splay(x, 0, pos);
            if(num[x] > 1)
            {
                --num[x];
                update(x);
                return;
            }
            if(child[x][0] * child[x][1] == 0)
            {
                root[pos] = child[x][0] + child[x][1];
                fa[root[pos]] = 0;
                child[x][0] = child[x][1] = fa[x] = 0;
                return;
            }
            int now = child[x][1];
            while(child[now][0]) now = child[now][0];
            fa[child[x][0]] = now;
            child[now][0] = child[x][0];
            root[pos] = child[x][1];
            fa[root[pos]] = 0;
            up(child[x][0]);
            child[x][0] = child[x][1] = num[x] = size[x]
            = fa[x] = 0;
            splay(now, 0, pos);
        }
        void insert(int pos, data &k)
        {
            int now = root[pos];
            if(!root[pos])
            {
                root[pos] = ++cnt;
                tree[cnt] = k;
                size[cnt] = num[cnt] = 1;
                sum[cnt] = k.v;
                return;
            }
            while(1)
            {    
                if(tree[now].a == k.a)
                {
                    ++num[now];
                    up(now);
                    break;
                }
                if(!child[now][k.a > tree[now].a])
                {
                    child[now][k.a > tree[now].a] = ++cnt;
                    tree[cnt] = k;
                    size[cnt] = num[cnt] = 1;
                    fa[cnt] = now;
                    sum[cnt] = k.v;
                    up(cnt);
                    splay(cnt, 0, pos);
                    break; 
                }
                now = child[now][k.a > tree[now].a];
            }
        }
    } using namespace splaytree;
    namespace segmenttree
    {
        void update(int l, int r, int x, int pos, data &k)
        {
            if(l == r)
            {
                root[x] = ++cnt;
                tree[cnt] = k;
                num[cnt] = size[cnt] = 1;
                sum[cnt] = k.v;
                return;
            }
            int mid = (l + r) >> 1;
            if(pos <= mid) update(l, mid, x << 1, pos, k);
            else update(mid + 1, r, x << 1 | 1, pos, k);
            int t = find(x, a[pos]);
            del(x, t); insert(x, k);
        }
        void build(int l, int r, int x)
        {
            if(l == r)
            {
                root[x] = ++cnt;
                num[cnt] = size[cnt] = 1;
                tree[cnt] = a[l];
                sum[cnt] = a[l].v;
                return;
            }
            int mid = (l + r) >> 1;
            build(l, mid, x << 1); 
            build(mid + 1, r, x << 1 | 1);
            for(int i = l; i <= r; ++i) insert(x, a[i]);
        }
        ll querybig(int l, int r, int x, int a, int b, data &k)
        {
            if(l > b || r < a) return 0;
            if(l >= a && r <= b) return getbig(x, k) % mod;
            int mid = (l + r) >> 1;
            return ((querybig(l, mid, x << 1, a, b, k) +
                    querybig(mid + 1, r, x << 1 | 1, a, b, k)) % mod);
        }
        ll querysmall(int l, int r, int x, int a, int b, data &k)
        {
            if(l > b || r < a) return 0;
            if(l >= a && r <= b) return getsmall(x, k) % mod;
            int mid = (l + r) >> 1;
            return ((querysmall(l, mid, x << 1, a, b, k) + 
                    querysmall(mid + 1, r, x << 1 | 1, a, b, k)) % mod);
        }
    } using namespace segmenttree;
    int main()
    {
        n = read(); m = read();
        for(int i = 1; i <= n; ++i) 
        {
            a[i].a = read(); a[i].v = read();
            ans = ((ans + B.query(50001, a[i].v) - B.query(a[i].a, a[i].v)) % mod + mod) % mod;
            B.update(a[i].a, a[i].v);
        }        
        build(1, n, 1);
        while(m--)
        {
            int x, y; x = read(); y = read();
            if(x > y) swap(x, y);
            if(x == y) 
            {
                printf("%lld
    ", ans);
                continue;
            }
            if(a[x].a < a[y].a) ans += a[x].v + a[y].v;
            else ans -= a[x].v + a[y].v;
            ll a1 = querybig(1, n, 1, x + 1, y - 1, a[x]);
            ll a2 = querysmall(1, n, 1, x + 1, y - 1, a[x]);
            ll a3 = querysmall(1, n, 1, x + 1, y - 1, a[y]);
            ll a4 = querybig(1, n, 1, x + 1, y - 1, a[y]);    
            ans = ((ans + a1 - a2 + a3 - a4) % mod + mod) % mod;
            update(1, n, 1, x, a[y]);    
            update(1, n, 1, y, a[x]);
            swap(a[x], a[y]);
            printf("%lld
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    比较.NET程序集(DLL或EXE)是否相同
    [转] JavaScript数组去重(12种方法)
    [转] js网络请求跨域问题汇总(携带cookie)
    [转] JS中arr.forEach()如何跳出循环
    [转] vue前端异常监控sentry实践
    [转] vue父组件触发子组件事件
    [转] vue 自定义组件使用v-model
    [转] Nginx配置性能优化
    [转] linux 查找文本过滤grep正则表达式命令详解用法
    [转] Nginx配置中的location、root、alias
  • 原文地址:https://www.cnblogs.com/19992147orz/p/6931078.html
Copyright © 2011-2022 走看看