bzoj3192: [JLOI2013]删除物品

又是一道玄学乱搞

本来我感觉是写两颗splay然后翻转什么的,后来发现可以乱搞

就是把第一个栈反过来,两个栈拼起来, 然后记录一个分割点,从大到小模拟,移动分割点,中间的经过的没被删除的元素就用树状数组维护下

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

int n,m;
LL s[110000];
int lowbit(int x){return x&-x;}
void change(int x,int k)
{
    while(x<=105000)
    {
        s[x]+=k;
        x+=lowbit(x);
    }
}
int getsum(int x)
{
    int ret=0;
    while(x>0)
    {
        ret+=s[x];
        x-=lowbit(x);
    }
    return ret;
}

struct node{int k,id;}a[110000];
bool cmp(node n1,node n2){return n1.k>n2.k;}
int lslen,ls[110000];
void LSH()
{
    lslen=m;
    for(int i=1;i<=m;i++)ls[i]=a[i].k;
    sort(ls+1,ls+lslen+1);
    lslen=unique(ls+1,ls+lslen+1)-ls-1;
    for(int i=1;i<=m;i++)
        a[i].k=lower_bound(ls+1,ls+lslen+1,a[i].k)-ls;
}//init
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    n=read(),m=read();
    for(int i=1;i<=n;i++)
        a[n-i+1].k=read(), a[i].id=i;
    for(int i=n+1;i<=n+m;i++)
        a[i].k=read(), a[i].id=i;
    m+=n;n++;LSH();
    sort(a+1,a+m+1,cmp);
    //n表示第n-1个位置和第n个位置不在一个栈中 
    
    for(int i=1;i<=m;i++)change(i,1);
    LL ans=0;
    for(int i=1;i<m;i++)
    {
        if(a[i].id<n-1)
        {
            ans+=getsum(n-1)-getsum(a[i].id);
        }
        else if(n<a[i].id) 
        {
            ans+=getsum(a[i].id-1)-getsum(n-1);
        }
        change(a[i].id,-1);
        n=a[i].id+1;
    }
    printf("%lld\n",ans);
    return 0;
}

 

posted @ 2018-06-26 13:36  AKCqhzdy  阅读(123)  评论(0编辑  收藏  举报