zoukankan      html  css  js  c++  java
  • bzoj3295

    cdq分治

    我们把每个数都视作插入和询问,那么每个询问就是当前的贡献。。。

    事实上这道题可以看做一个三维偏序:(t,v,pos) 插入时间,值,插入位置

    两个数当且仅当形成逆序对时是x,y,x的插入时间比y早,x的值比y小,x在y的后面,x的值比y大,x在y的前面。

    那么就可以cdq分治了

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define N 400010
    #define lowbit(i) i&-i
    struct query
    {
        int v,id,pos,type;
    }q[N];
    int n,tot,m;
    ll a[N],b[N],tree[N],ans[N],pos[N];
    bool flag[N];
    vector<query> c;
    inline void update(int pos,int delta) {for(int i=pos;i<=n;i+=lowbit(i)) tree[i]+=delta; }
    inline ll sum(int pos) {ll ret=0; for(int i=pos;i;i-=lowbit(i)) ret+=tree[i]; return ret;}
    inline bool cp1(query x,query y) {if(x.pos!=y.pos) return x.pos<y.pos; return x.type<y.type;}
    inline bool cp2(query x,query y) {if(x.pos!=y.pos) return x.pos>y.pos; return x.type<y.type;}
    void cdq(int l,int r)
    {   
        if(l>=r) return;
        int mid=(l+r)>>1;
        cdq(l,mid); cdq(mid+1,r);
        c.clear();
        for(int i=l;i<=mid;++i) if(q[i].type==1) c.push_back(q[i]);
        for(int i=mid+1;i<=r;++i) if(q[i].type==2) c.push_back(q[i]);
        sort(c.begin(),c.end(),cp1);
        for(int i=0;i<c.size();++i)
        {
            if(c[i].type==1) update(c[i].v,1);
            if(c[i].type==2) ans[c[i].id]+=sum(n)-sum(c[i].v);
        }
        for(int i=0;i<c.size();++i) if(c[i].type==1) update(c[i].v,-1);
        sort(c.begin(),c.end(),cp2);
        for(int i=0;i<c.size();++i)
        {
            if(c[i].type==1) update(c[i].v,1);
            if(c[i].type==2) ans[c[i].id]+=sum(c[i].v-1);
        }
        for(int i=0;i<c.size();++i) if(c[i].type==1) update(c[i].v,-1);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&a[i]);
            pos[a[i]]=i;
        }
        for(int i=1;i<=m;++i)
        {
            scanf("%d",&b[i]);
            flag[b[i]]=1;
        }
        int t=0;
        for(int i=1;i<=n;++i) if(!flag[a[i]])
        {
             q[++tot].v=a[i];
             q[tot].type=1;
             q[tot].pos=pos[a[i]];
             q[++tot].v=a[i];
             q[tot].type=2;
             q[tot].pos=pos[a[i]];
             q[tot].id=++t;
        }
        for(int i=m;i;--i)
        {
            q[++tot].v=b[i];
            q[tot].pos=pos[b[i]];
            q[tot].type=1;
            q[++tot].v=b[i];
            q[tot].pos=pos[b[i]];
            q[tot].type=2;
            q[tot].id=++t;
        }
        cdq(1,tot);
        for(int i=1;i<=n;++i) ans[i]+=ans[i-1];
        for(int i=n;i>=n-m+1;--i) printf("%lld
    ",ans[i]);
    //  fclose(stdin);
    //  fclose(stdout);
        return 0;
    }
    View Code
  • 相关阅读:
    预习作业一
    20145234黄斐《java程序设计基础》第一周
    预习作业3
    开源 人脸识别 openface 实用介绍 实例演示 训练自己的模型
    ubuntu 开机 输入密码 无法进入
    linux anaconda 管理 python 包
    如何从零开始做一个蓝牙机械键盘
    keil中结构体跨文件调用
    GPRS 通信
    如何查找EI 及SCI 索引
  • 原文地址:https://www.cnblogs.com/19992147orz/p/6387014.html
Copyright © 2011-2022 走看看