zoukankan      html  css  js  c++  java
  • CF785E Anton and Permutation

    CF785E Anton and Permutation

    CF785E Anton and Permutation

    带交换逆序对。

    前面(位置)比它大的数的个数+后面比它小的个数,很显然这就是一个三维偏序的问题(时间上也要满足偏序)

    首先把第一维时间排序(原本就有序了)

    然后对位置进行CDQ分治,对右半部分计算左半部分:位置在其左边值大,位置在其右边值小的方案

    注意:左右两半部分在位置上是独立有序的,在计算时还要看另一边是否满足位置上的限制

    这样就能得到当前区间,每一个操作对应的逆序对,如果是插入,对应答案就加上,如果是删除,就剪掉

    注意上面的这一个过程,其实只是单独考虑每个操作对答案的影响,最后还要把答案求个前缀和

    cdq分治题解代码:

    view code
    #include <iostream>
    #include <cstdio>
    #define ll long long
    using namespace std;
    const int N=2e5+10,M=5e4+10;
    int n;
    int val[N],t[N];
    ll ans[M];
    struct node
    {
    	int a,b,c;
    	int type,id;
    }v[N+4*M],w[N+4*M];
    inline int lowbit(int x)
    {
    	return x&(-x);
    }
    inline void change(int x,int c)
    {
    	for(int i=x;i<=n;i+=lowbit(i))
    		t[i]+=c;
    }
    inline int query(int x)
    {
    	int res=0;
    	for(int i=x;i>=1;i-=lowbit(i))
    		res+=t[i];
    	return res;
    }
    inline void CDQ(int l,int r)
    {
    	if(l==r) return;
    	int mid=(l+r)/2,p,q;
    	CDQ(l,mid),CDQ(mid+1,r);
    	p=l,q=mid+1;
    	while(q<=r)//计算左边位置小值大 
    	{
    		while(p<=mid&&v[p].b<=v[q].b) change(v[p].c,v[p].type),p++;
    		ans[v[q].id]+=v[q].type*(query(n)-query(v[q].c)),q++;
    	}
    	for(int i=l;i<p;i++) change(v[i].c,-v[i].type);
    	p=mid,q=r;
    	while(q>mid)//计算左边位置大值小 
    	{
    		while(p>=l&&v[p].b>=v[q].b) change(v[p].c,v[p].type),p--;
    		ans[v[q].id]+=v[q].type*query(v[q].c-1),q--;
    	}
    	for(int i=mid;i>p;i--) change(v[i].c,-v[i].type);
    	p=l,q=mid+1;
    	for(int i=l;i<=r;i++)//归并排序
    	{
    		if((p<=mid&&v[p].b<=v[q].b)||q>r) w[i]=v[p++];
    		else w[i]=v[q++];
    	} 
    	for(int i=l;i<=r;i++) v[i]=w[i];
    }
    int main()
    {
    	int m,tot=0,a,b;
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)
    		val[i]=i,v[++tot]=(node){tot,i,i,1,0};
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%d%d",&a,&b);
    		v[++tot]=(node){tot,a,val[a],-1,i};
    		v[++tot]=(node){tot,b,val[b],-1,i};
    		v[++tot]=(node){tot,a,val[b],1,i};
    		v[++tot]=(node){tot,b,val[a],1,i};
    		swap(val[a],val[b]);
    	}
    	CDQ(1,tot);
    	for(int i=1;i<=m;i++)
    		ans[i]+=ans[i-1];
    	for(int i=1;i<=m;i++)
    		printf("%lld
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    JuiceSSH:安卓平台免费好用的 SSH 客户端
    git&github-本地库推送到远程库
    git&githib-给远程库取别名
    Git分支管理的本质
    MySQL学习笔记(一)--逻辑架构学习
    mysql-主从备份问题小结
    Docker--数据管理之Volumes
    初识OpenSSH--1
    一个最简单的Dockfile实践
    构词法2
  • 原文地址:https://www.cnblogs.com/Akmaey/p/14648581.html
Copyright © 2011-2022 走看看