bzoj 2141: 排队

2141: 排队

Description

排排坐,吃果果,生果甜嗦嗦,大家笑呵呵。你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和。红星幼儿园的小朋友们排起了长长地队伍,准备吃果果。不过因为小朋友们的身高有所区别,排成的队伍高低错乱,极不美观。设第i个小朋友的身高为hi,我们定义一个序列的杂乱程度为:满足ihj的(i,j)数量。幼儿园阿姨每次会选出两个小朋友,交换他们的位置,请你帮忙计算出每次交换后,序列的杂乱程度。为方便幼儿园阿姨统计,在未进行任何交换操作时,你也应该输出该序列的杂乱程度。

Input

第一行为一个正整数n,表示小朋友的数量;第二行包含n个由空格分隔的正整数h1,h2,…,hn,依次表示初始队列中小朋友的身高;第三行为一个正整数m,表示交换操作的次数;以下m行每行包含两个正整数ai和bi¬,表示交换位置ai与位置bi的小朋友。

Output

输出文件共m行,第i行一个正整数表示交换操作i结束后,序列的杂乱程度。

Sample Input

【样例输入】

3
130 150 140
2
2 3
1 3

Sample Output

1
0
3
【样例说明】
未进行任何操作时,(2,3)满足条件;
操作1结束后,序列为130 140 150,不存在满足i<j且hi>hj的(i,j)对;
操作2结束后,序列为150 140 130,(1,2),(1,3),(2,3)共3对满足条件的(i,j)。
【数据规模和约定】
对于100%的数据,1≤m≤2*103,1≤n≤2*104,1≤hi≤109,ai≠bi,1≤ai,bi≤n。
 
题解:
 
一道动态逆序对的题。
 
对于交换,拆成两个删除,两个插入,注意一开始要把所有数插入。。然后直接上cdq分治。
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=20005;
const int M=2005;
struct node
{
    int a,id;
}A[N];
struct Node
{
    int a,b,c,id,No;
}p[(M<<2)+N],q[(M<<2)+N];
int n,m,Q,tot,i,k,x,y,h[N],t[N],ans[M];
inline void read(int &v){ 
    char ch,fu=0;
    for(ch='*'; (ch<'0'||ch>'9')&&ch!='-'; ch=getchar());
    if(ch=='-') fu=1, ch=getchar();
    for(v=0; ch>='0'&&ch<='9'; ch=getchar()) v=v*10+ch-'0';
    if(fu) v=-v;
}
bool cmp(const node&x,const node&y)
{
    return x.a<y.a;
}
bool Cmp(const Node&x,const Node&y)
{
    if(x.a!=y.a) return x.a<y.a;
    return x.b<y.b;
}
void update(int x,int y)
{
    while(x<=k) t[x]+=y,x+=x&-x;
}
int solve(int x)
{
    int ans=0;
    while(x) ans+=t[x],x-=x&-x;
    return ans;
}
void add(int x,int y,int z,int Q)
{
    p[++tot].id=tot;p[tot].No=Q;
    p[tot].a=x;p[tot].b=y;p[tot].c=z;
}
void solve(int l,int r)
{
    if(l==r) return;
    int mid=(l+r)>>1,i;
    for(i=l;i<=r;i++)
    {
        if(p[i].id<=mid) update(p[i].b,p[i].c);
        if(p[i].id>mid) ans[p[i].No]+=p[i].c*(solve(k)-solve(p[i].b));
    }
    for(i=l;i<=r;i++)
        if(p[i].id<=mid) update(p[i].b,-p[i].c);
    for(i=r;i>=l;i--)
    {
        if(p[i].id<=mid) update(p[i].b,p[i].c);
        if(p[i].id>mid) ans[p[i].No]+=p[i].c*solve(p[i].b-1);
    }
    for(i=l;i<=r;i++)
        if(p[i].id<=mid) update(p[i].b,-p[i].c);
    int L=l,R=mid+1;
    for(i=l;i<=r;i++)
        if(p[i].id<=mid) q[L++]=p[i];else q[R++]=p[i];
    for(i=l;i<=r;i++) p[i]=q[i];
    solve(l,mid);solve(mid+1,r);
}
int main()
{
    read(n);
    for(i=1;i<=n;i++) read(A[i].a),A[i].id=i;
    sort(A+1,A+n+1,cmp);
    k=1;h[A[1].id]=1;
    for(i=2;i<=n;i++)
    {
        if(A[i].a!=A[i-1].a) k++;
        h[A[i].id]=k;
    }
    for(i=1;i<=n;i++) p[++tot].id=tot,p[tot].a=i,p[tot].b=h[i],p[tot].c=1;
    read(m);
    for(i=1;i<=m;i++)
    {
        read(x),read(y);
        add(x,h[x],-1,++Q);add(y,h[y],-1,Q);
        add(x,h[y],1,Q);add(y,h[x],1,Q);
        swap(h[x],h[y]);
    }
    sort(p+1,p+tot+1,Cmp);
    solve(1,tot);
    printf("%d\n",ans[0]);
    for(i=1;i<=m;i++) ans[i]+=ans[i-1],printf("%d\n",ans[i]);
    return 0;
}

  

posted @ 2016-08-15 10:38  lwq12138  阅读(229)  评论(0编辑  收藏  举报