• 洛谷P3157 [CQOI2011]动态逆序对


    题目大意:

    给定(1)(n)的一个排列,按照给定顺序依次删除(m)个元素,计算每个元素删除之前整个序列的逆序对数量

    基本套路:删边变加边

    那么我们不就是求满足(pos_i<pos_j,tim_i<tim_j,num_i>num_j)的数量嘛

    先按(tim)排序,然后归并(pos_i),树状数组(num_i)

    不过这道题我们需要正反跑两个(cdq),因为我们需要分开统计(pos_i<pos_j,num_i>num_j)(pos_i>pos_j,num_i<num_j)的贡献

    但是我压缩到一个(cdq)里了(emmmm)

    需要稍微注意的一点是,我们需要把答案累加的令一个(ret_i)数组中,其中(ret_i)表示在(i)时刻新产生了多少逆序对,最后还需要输出前缀和

    不粘代码是不是太短了

    #include<bits/stdc++.h>
    using namespace std;
    namespace red{
    #define int long long
    #define mid ((l+r)>>1)
    #define lowbit(x) ((x)&(-x))
    	inline int read()
    	{
    		int x=0;char ch,f=1;
    		for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
    		if(ch=='-') f=0,ch=getchar();
    		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    		return f?x:-x;
    	}
    	const int N=1e5+10;
    	int n,m,idx,tot;
    	int pos[N];
    	int st[N];
    	int ret[N];
    	struct point
    	{
    		int x,id,tim;
    		int val;
    		inline bool operator < (const point &t) const
    		{
    			if(tim^t.tim) return tim<t.tim;
    			return id<t.id;
    		}
    	}a[N<<2],t[N<<2];
    	int tr[N<<1];
    	inline void update(int x,int k)
    	{
    		for(int i=x;i<=n;i+=lowbit(i)) tr[i]+=k;
    	}
    	inline int query(int y)
    	{
    		int ret=0;
    		for(int i=y;i;i-=lowbit(i))
    			ret+=tr[i];
    		return ret;
    	}
    	inline void cdq(int l,int r)
    	{
    		if(l==r) return;
    		cdq(l,mid);
    		cdq(mid+1,r);
    		int tl=l,tr=mid+1,tot=l;
    		while(tl<=mid&&tr<=r)
    		{
    			if(a[tl].id<=a[tr].id) update(a[tl].x,1),t[tot++]=a[tl++];
    			else ret[a[tr].tim]+=query(n)-query(a[tr].x),t[tot++]=a[tr++];
    		}
    		while(tl<=mid) update(a[tl].x,1),t[tot++]=a[tl++];
    		while(tr<=r) ret[a[tr].tim]+=query(n)-query(a[tr].x),t[tot++]=a[tr++];
    		for(int i=l;i<=mid;++i) update(a[i].x,-1);
    		tl=mid,tr=r;
    		while(tl>=l&&tr>=mid+1)
    		{
    			if(a[tl].id>=a[tr].id) update(a[tl].x,1),--tl;
    			else ret[a[tr].tim]+=query(a[tr].x-1),--tr;
    		}
    		while(tl>=l) update(a[tl].x,1),--tl;
    		while(tr>=mid+1) ret[a[tr].tim]+=query(a[tr].x-1),--tr;
    		for(int i=l;i<=mid;++i) update(a[i].x,-1);
    		for(int i=l;i<=r;++i) a[i]=t[i];
    	}
    	inline void main()
    	{
    		n=read(),m=read();
    		for(int x,i=1;i<=n;++i)
    		{
    			x=read();
    			pos[x]=i;
    			a[i].x=x;
    			a[i].id=i;
    			a[i].tim=1;
    		}
    		for(int x,tmp,i=1;i<=m;++i)
    		{
    			x=read();
    			tmp=pos[x];
    			a[tmp].tim=m-i+2;
    		}
    		sort(a+1,a+n+1);
    		cdq(1,n);
    		for(int i=1;i<=m+1;++i) ret[i]+=ret[i-1];
    		for(int i=m+1;i>=2;--i) printf("%lld
    ",ret[i]);
    	}
    }
    signed main()
    {
    	red::main();
    	return 0;
    }
    
  • 相关阅读:
    Solr6.6环境安装及core的创建(win7环境)
    使用Druid作为数据源
    Windows远程数据同步工具cwRsync
    解读zookeeper的配置项
    堵塞与非堵塞原理
    Apache Hadoop2.0之HDFS均衡操作分析
    转到简书去了
    淘宝技术这十年概要
    Facebook广告API系列 Business Manager
    Facebook广告API系列 3 Ads Management
  • 原文地址:https://www.cnblogs.com/knife-rose/p/12045586.html
Copyright © 2020-2023  润新知