国家集训队 排队

题目描述

题解:

将交换看作两个插入+两个删除。

然后CDQ。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 30050
#define ll long long
inline int rd()
{
    int f=1,c=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
    return f*c;
}
int n,m,cnt,stu[N];
struct Pair
{
    int x,id;
}tk[N];
bool cmp(Pair a,Pair b)
{
    return a.x<b.x;
}
struct node
{
    int pos,val,id,wgt;
    node(){}
    node(int p,int v,int i,int w):pos(p),val(v),id(i),wgt(w){}
}p[N],tmp[N];
void Sort(int l,int r)
{
    int mid = (l+r)>>1;
    int i=l,j=mid+1,k=l;
    while(i<=mid&&j<=r)
    {
        while(i<=mid&&p[i].pos<=p[j].pos)
        {
            tmp[k]=p[i];
            i++,k++;
        }
        while(j<=r&&p[i].pos>p[j].pos)
        {
            tmp[k]=p[j];
            j++,k++;
        }
    }
    while(i<=mid)
    {
        tmp[k]=p[i];
        i++,k++;
    }
    while(j<=r)
    {
        tmp[k]=p[j];
        j++,k++;
    }
    for(i=l;i<=r;i++)
        p[i]=tmp[i];
}
int f[N];
void up(int x,int d)
{
    if(!x)return ;
    while(x<N)f[x]+=d,x+=(x&-x);
}
int down(int x)
{
    if(!x)return 0;
    int ret = 0;
    while(x)ret+=f[x],x-=(x&-x);
    return ret;
}
int k = 0;
ll ans[N];
void cdq(int l,int r)
{
    if(l==r)return ;
    int mid = (l+r)>>1;
    cdq(l,mid),cdq(mid+1,r);
    Sort(l,mid),Sort(mid+1,r);
    int i,j;
    j=l;
    for(i=mid+1;i<=r;i++)
    {
        while(j<=mid&&p[j].pos<=p[i].pos)up(p[j].val,p[j].wgt),j++;
        ans[p[i].id]+=p[i].wgt*(down(k)-down(p[i].val));
    }
    for(j=j-1;j>=l;j--)up(p[j].val,-p[j].wgt);
    j=mid;
    for(i=r;i>mid;i--)
    {
        while(j>=l&&p[j].pos>=p[i].pos)up(p[j].val,p[j].wgt),j--;
        ans[p[i].id]+=p[i].wgt*down(p[i].val-1);
    }
    for(j=j+1;j<=mid;j++)up(p[j].val,-p[j].wgt);
}
int main()
{
    n=rd();
    for(int x,i=1;i<=n;i++)
    {
        x=rd();
        tk[i].x=x,tk[i].id=i;
    }
    sort(tk+1,tk+n+1,cmp);
    for(int las=-1,i=1;i<=n;i++)
    {
        if(las!=tk[i].x)
        {
            las=tk[i].x;
            k++;
        }
        int j = tk[i].id;
        p[j]=node(j,k,0,1);
        stu[j] = k;
    }
    m=rd();
    for(int l,r,i=1;i<=m;i++)
    {
        l=rd(),r=rd();
        p[++n]=node(l,stu[l],i,-1);
        p[++n]=node(r,stu[r],i,-1);
        swap(stu[l],stu[r]);
        p[++n]=node(l,stu[l],i,1);
        p[++n]=node(r,stu[r],i,1);
    }
    cdq(1,n);
    for(int i=1;i<=m;i++)ans[i]+=ans[i-1];
    for(int i=0;i<=m;i++)printf("%lld\n",ans[i]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/LiGuanlin1124/p/10143365.html