关于两种不同写法的CDQ分治
查看原帖
关于两种不同写法的CDQ分治
230804
Durancer楼主2021/7/20 22:00

自己的思路挺常见,正着扫,反着扫,用树状数组维护 deldel 值。

但是用两种不同写法的 CDQ\text{CDQ} 分治一个爆零,一个满分,有没有大佬佬能解答一下qwq。

(除了CDQ分治函数其他的都是一模一样的)

满分:

#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define int long long
using namespace std;
const int N=1e5+9;
int n;
int m;
int t[N];
struct node{
	int val;
	int del;
	int ans;
} a[N];
int pos[N];
int origin;
int read()
{
	int f=1,x=0;
	char s=getchar();
	while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
	while(s>='0'&&s<='9'){x=(x<<1)+(x<<3)+(s^'0');s=getchar(); }
	return f*x;
}
bool cmp1(node a,node b) 
{
	return a.val<b.val;
}
bool cmp2(node a,node b) 
{
	return a.del<b.del;
}
int lowbit(int x)
{
	return x&(-x);	
}
void add(int x,int val)
{
	//cout<<"x= "<<x<<endl; 
	while(x<=n+1)
	{
		t[x]+=val;
		x+=lowbit(x);
	}
}
int query(int x)
{//
	int ret=0;
	while(x)
	{
		ret+=t[x];
		x-=lowbit(x);	
	}	
	return ret;
} 
void CDQ(int l,int r) 
{
	if(r-l==1) return;
	int mid=(l+r)/2;
	CDQ(l,mid);
	CDQ(mid,r);
	int i=l+1;
	int j=mid+1;
	for(;i<=mid;i++)
	{
		while(a[i].val>a[j].val&&j<=r) 
		{
			add(a[j].del,1);
			j++;
		}
		a[i].ans+=query(m+1)-query(a[i].del);
	}
	i=l+1;
	j=mid+1;//回撤操作
	for(;i<=mid;i++) 
	{
		while(a[i].val>a[j].val&&j<=r) 
		{
			add(a[j].del,-1);
			j++;
		}
	}
	i=mid;
	j=r;
	for(;j>mid;j--) 
	{
		while(a[j].val<a[i].val&&i>l) 
		{
			add(a[i].del,1);
			i--;
		}
		a[j].ans+=query(m+1)-query(a[j].del);
	}
	i=mid;
	j=r;
	for(;j>mid;j--) 
	{
		while(a[j].val<a[i].val&&i>l) 
		{
			add(a[i].del,-1);
			i--;
		}
	}
	sort(a+l+1,a+r+1,cmp1);
}
signed main() 
{
	n=read();
	m=read();
	for(int i=1; i<=n; i++) 
	{
		a[i].val=read(); 
		pos[a[i].val]=i;
	}
	for(int i=1; i<=m; i++) 
	{
		int p=read();
		a[pos[p]].del=i;
	}
	for(int i=1; i<=n; i++) 
		if(a[i].del==0)
			a[i].del=m+1;
	for(int i=1; i<=n; i++) 
	{
		origin+=query(n+1)-query(a[i].val);
		add(a[i].val,1);
	}
	for(int i=1; i<=n; i++)
		add(a[i].val,-1);
	CDQ(0,n);
	sort(a+1,a+n+1,cmp2);
	for(int i=1; i<=m; i++) 
	{
		printf("%lld\n",origin);
		origin-=a[i].ans;
	}
	return 0;
}

0分:

#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define int long long
#define mid ((l+r)>>1)
using namespace std;
const int N=1e5+9;
int n;
int m;
int t[N];
struct node{
	int val;
	int del;
	int ans;
} a[N];
int pos[N];
int origin;
int read()
{
	int f=1,x=0;
	char s=getchar();
	while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
	while(s>='0'&&s<='9'){x=(x<<1)+(x<<3)+(s^'0');s=getchar(); }
	return f*x;
}
bool cmp1(node a,node b) 
{
	return a.val<b.val;
}
bool cmp2(node a,node b) 
{
	return a.del<b.del;
}
int lowbit(int x)
{
	return x&(-x);	
}
void add(int x,int val)
{
	//cout<<"x= "<<x<<endl; 
	while(x<=n+1)
	{
		t[x]+=val;
		x+=lowbit(x);
	}
}
int query(int x)
{//
	int ret=0;
	while(x)
	{
		ret+=t[x];
		x-=lowbit(x);	
	}	
	return ret;
} 
void CDQ(int l,int r) 
{
	if(l==r) return;
	CDQ(l,mid);
	CDQ(mid+1,r);
	int i=l;
	int j=mid+1;
	for(;i<=mid;i++)
	{
		while(a[i].val>a[j].val&&j<=r) 
		{
			add(a[j].del,1);
			j++;
		}
		a[i].ans+=query(m+1)-query(a[i].del);
	}
	i=l;
	j=mid+1;//回撤操作
	for(;i<=mid;i++) 
	{
		while(a[i].val>a[j].val&&j<=r) 
		{
			add(a[j].del,-1);
			j++;
		}
	}
	i=mid;
	j=r;
	for(;j>mid;j--) 
	{
		while(a[j].val<a[i].val&&i>l) 
		{
			add(a[i].del,1);
			i--;
		}
		a[j].ans+=query(m+1)-query(a[j].del);
	}
	i=mid;
	j=r;
	for(;j>mid;j--) 
	{
		while(a[j].val<a[i].val&&i>l) 
		{
			add(a[i].del,-1);
			i--;
		}
	}
	sort(a+l,a+r+1,cmp1);
}
signed main() 
{
	n=read();
	m=read();
	for(int i=1; i<=n; i++) 
	{
		a[i].val=read(); 
		pos[a[i].val]=i;
	}
	for(int i=1; i<=m; i++) 
	{
		int p=read();
		a[pos[p]].del=i;
	}
	for(int i=1; i<=n; i++) 
		if(a[i].del==0)
			a[i].del=m+1;
	for(int i=1; i<=n; i++) 
	{
		origin+=query(n+1)-query(a[i].val);
		add(a[i].val,1);
	}
	for(int i=1; i<=n; i++)
		add(a[i].val,-1);
	CDQ(1,n);
	sort(a+1,a+n+1,cmp2);
	for(int i=1; i<=m; i++) 
	{
		printf("%lld\n",origin);
		origin-=a[i].ans;
	}
	return 0;
}
2021/7/20 22:00
加载中...