BZOJ 3295 转

树状数组套主席树,看的云里雾里,好不容易懂了一点。。。弱成渣。。。

#include<cstring>
#include<string>
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstdlib>
#include<cmath>
#include<vector>
//#pragma comment(linker, "/STACK:1024000000,1024000000");

using namespace std;

#define INF 0x3f3f3f3f
#define maxn 100005

int n,m,cnt;
long long sum;
long long ans[maxn];
bool vis[maxn];
int b[maxn];
int a[maxn],indx[maxn];
int root[maxn];

void init()
{
    memset(root,0,sizeof root);
    memset(vis,false,sizeof vis);
    cnt=0;
    sum=0;
}

struct node
{
    int l,r;
    int sum;
    node()
    {
        l=r=sum=0;
    }
} t[90*maxn];

void update(int &rt,int pre,int pos,int l,int r)
{
    if(!rt) t[rt=++cnt]=t[pre];
    t[rt].sum++;
    if(l==r&&r==pos)
    {
        t[rt].sum=1;
        return ;
    }
    int mid=l+r>>1;
    if(pos<=mid) update(t[rt].l,t[pre].l,pos,l,mid);
    else update(t[rt].r,t[pre].r,pos,mid+1,r);
}

int query1(int rt,int pos,int l,int r)
{
    if(l==r&&r==pos)
    {
        return 0;
    }
    int mid=l+r>>1;
    if(pos<=mid) return query1(t[rt].l,pos,l,mid)+t[t[rt].r].sum;
    else return query1(t[rt].r,pos,mid+1,r);
}

int query2(int rt,int pos,int l,int r)
{
    if(l==r&&r==pos)
    {
        return 0;
    }
    int mid=l+r>>1;
    if(pos<=mid) return query2(t[rt].l,pos,l,mid);
    else return query2(t[rt].r,pos,mid+1,r)+t[t[rt].l].sum;
}

int lowbit(int x)
{
    return x&-x;
}

void add(int x,int pos)
{
    for(; x<=n; x+=lowbit(x)) update(root[x],root[x],pos,1,n);
}

long long ask(int x,int pos)
{
    long long temp=0;
    for(int i=x; i>0; i-=lowbit(i)) temp+=query1(root[i],pos,1,n);
    for(int i=n; i>0; i-=lowbit(i)) temp+=query2(root[i],pos,1,n);
    for(int i=x; i>0; i-=lowbit(i)) temp-=query2(root[i],pos,1,n);
    return temp;
}

int main()
{
    scanf("%d%d",&n,&m);
    init();
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&a[i]);
        indx[a[i]]=i;
    }
    for(int i=0; i<m; i++)
    {
        scanf("%d",&b[m-i-1]);
        vis[b[m-i-1]]=1;
    }
    for(int i=1; i<=n; i++)
    {
        if(!vis[a[i]])
        {
            add(i,a[i]);
            sum+=ask(i,a[i]);
        }
    }
    for(int i=0; i<m; i++)
    {
        add(indx[b[i]],b[i]);
        sum+=ask(indx[b[i]],b[i]);
        ans[i]=sum;
    }
    for(int i=m-1; i>=0; i--)
    {
        printf("%lld\n",ans[i]);
    }
    return 0;
}
时间: 2024-10-06 22:21:45

BZOJ 3295 转的相关文章

主席树初探 &amp; bzoj 3295: [Cqoi2011] 动态逆序对 题解

[原题] 3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 778  Solved: 263 [Submit][Status] Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数. Input 输入第一行包含两个整数n和m,即初始元素的个数和删除的元

BZOJ 3295:[Cqoi2011]动态逆序对(三维偏序 CDQ分治+树状数组)

http://www.lydsy.com/JudgeOnline/problem.php?id=3295 题意:简单明了. 思路:终于好像有点明白CDQ分治处理三维偏序了.把删除操作看作是插入操作,那么可以按照插入的时间顺序看作是一维x,插入的数在原本序列的下标是一维y,插入的数本身是一维z.那么问题可以转化成每插入一个数(xx,yy,zz),求有多少个数(x,y,z)使得 x < xx,y < yy,z > zz .一开始先对 x 进行排序,然后进行CDQ分治.这样可以干掉一维,保证随

【BZOJ 3295】 [Cqoi2011]动态逆序对

3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1373  Solved: 465 [Submit][Status][Discuss] Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数. Input 输入第一行包含两个整数n和m,即初始元素的个数

【刷题】BZOJ 3295 [Cqoi2011]动态逆序对

Description 对于序列A,它的逆序对数定义为满足iAj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数 Input 输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数. 以下n行每行包含一个1到n之间的正整数,即初始排列. 以下m行每行一个正整数,依次为每次删除的元素. N<=100000 M<=50000 Output 输出包含m行,依次为删除每个元素之前,逆序对的个数. Sample In

BZOJ 3295: [Cqoi2011]动态逆序对 cdq分治

https://www.lydsy.com/JudgeOnline/problem.php?id=3295 这个妹妹我曾见过的~~~ 之前应该在校内oj写了,似乎还写过题解?发现没写博客就重新水一遍代码水一篇博客好了. 把找逆序对的过程想成一个一个往里塞数字然后找每个数字可以组成的逆序对,把最后要去掉的几个也想成往里塞,所以加一个时间维度用cdq求三维偏序. 1 #include<iostream> 2 #include<cstdio> 3 #include<algorith

bzoj 3295 动态逆序对 CDQ分支

容易看出ans[i]=ans[i-1]-q[i],q[i]为删去第i个数减少的逆序对. 先用树状数组算出最开始的逆序对,预处理出每个数前边比它大的和后边比它小的,就求出了q[i]的初始值. 设b[i]是第i个删除的数,pos[i]为i在数列里的位置. 对q[i]产生影响的是   1. j<i,pos[b[j]]<pos[b[i]],b[j]>b[i].  2.j<i,pos[b[j]]>pos[b[i]],b[j]<b[i]. 因为是三维的,所以我们套一层cdq. 1

BZOJ 3295 【Cqoi2011】 动态逆序对

Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数. Input 输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数.以下n行每行包含一个1到n之间的正整数,即初始排列.以下m行每行一个正整数,依次为每次删除的元素. Output 输出包含m行,依次为删除每个元素之前,逆序对的个数. HINT N<=100000 M<

bzoj 3295: [Cqoi2011]动态逆序对(树套树 or CDQ分治)

Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数. Input 输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数.以下n行每行包含一个1到n之间的正整数,即初始排列.以下m行每行一个正整数,依次为每次删除的元素. Output 输出包含m行,依次为删除每个元素之前,逆序对的个数. Sample Input 5 4 1 5 3

bzoj 3295: [Cqoi2011]动态逆序对

2016-06-22 这个题本想昨天晚上做来,但昨晚狂风大作,暴雨倾盆(听说我们学校最落后的一堵墙都被吹到了),停电了,我只能无聊的瞭望了教学楼一晚上...... 这个题把删除看成插入的话,插入一个点 新增逆序对就是比他早插入的,位置靠前,数比他大或 位置靠后,数比他小.那这就是个三维偏序集,可以用CDQ搞搞了. 这个题也能用树套树,树状数组归并排序做(以后有时间要写一写,恐怕是没可能了%>_<%). 1 #include<cstdio> 2 #include<iostrea

COGS 1715 &amp; bzoj 3295 [CQOI2011]动态逆序对 题解

(又是一道树套树……自己真是玩疯了……) (题意略) 从网上也看过题解,好像解法很多……比如CDQ+树状数组,树状数组套主席树,树状数组套平衡树……我用的是树状数组套splay. (我会说是因为我不会写CDQ和树状数组套主席树么= =) (不得不吐槽,为啥splay这么快= =) 也没啥可说的,我写的是在线算法,只要在删除一个元素之前统计它前面比它大的数和后面比它小的数的个数(区间求和用树状数组,统计比它小/大的数的个数用平衡树写),把答案减掉对应数值即可. 鉴于这题卡常,我就加了快读和各种in