【CDQ 分治】萌新 AC 后求问灵异事件
查看原帖
【CDQ 分治】萌新 AC 后求问灵异事件
356003
Moeebius楼主2022/8/12 22:15

如下是我的 CDQ 代码:

int n,k;
struct Node
{
	int a,b,c,cnt,ans;
}a[100005];
bool cmp1(const Node &a, const Node &b)
{
	return a.a<b.a || a.a==b.a && a.b<b.b || a.a==b.a && a.b==b.b && a.c<b.c;
}
bool cmp2(const Node &a, const Node &b)
{
	return a.b<b.b || a.b==b.b && a.c<b.c;
}

Node b[100005];
int tot=1;
int BIT[200005],final[200005];
#define lowbit(x) (x&(-x))
il void add(int pos, int val)
{
	while(pos<=k) BIT[pos]+=val,pos+=lowbit(pos);
}
il int qry(int pos)
{
	int __ans=0;while(pos) __ans+=BIT[pos],pos-=lowbit(pos);return __ans;
}

在 CDQ 的 solve 函数中,我们需要一个变量来存放结果。

当我这样写的时候,获得了 WA 10pts\mathtt{WA\ 10pts} 的成绩:

// ans 数组用于记录答案,final 数组用于输出最终答案
int ans[200001];
void solve(int l, int r)
{
	if(l>=r) return;
	int mid=(l+r)>>1;
	solve(l,mid);solve(mid+1,r);
	sort(b+l,b+mid+1,cmp2);sort(b+mid+1,b+r+1,cmp2);
	// cerr<<l<<' '<<r<<endl;
	int i=mid+1,j=l;
	while(i<=r)
	{
		// cerr<<">"<<i<<' '<<j<<endl;
		while(j<=mid && b[j].b<=b[i].b)
		{
			add(b[j].c,b[j].cnt);
			++j;
		}
		ans[i]+=qry(b[i].c);//注意这一行
		i++;
	}
	For(k,l,j-1) add(b[k].c,-b[k].cnt);
}

int final[200005];

signed main()
{
	read(n,k);
	For(i,1,n) read(a[i].a,a[i].b,a[i].c);
	sort(a+1,a+1+n,cmp1);
	b[1]=a[1];b[1].cnt=1;
	For(i,2,n)
	{
		if(a[i].a==a[i-1].a && a[i].b==a[i-1].b && a[i].c==a[i-1].c)
		{
			b[tot].cnt++;
		}
		else
		{
			b[++tot]=a[i];
			b[tot].cnt=1;
		}
	} // 去重
	solve(1,tot);
	For(i,1,tot)
	{
		final[ans[i]+b[i].cnt-1]+=b[i].cnt; //注意这里
	}
	For(i,0,n-1) cout<<final[i]<<endl;
	return 0;
}

但是这样写则可以 AC\mathtt{AC}

//用 Node 结构体中的元素 b[i].ans 记录答案,用 final 数组计算输出
void solve(int l, int r)
{
	if(l==r) return;
	int mid=(l+r)>>1;
	solve(l,mid);solve(mid+1,r);
	sort(b+l,b+mid+1,cmp2);sort(b+mid+1,b+r+1,cmp2);
	// cerr<<l<<' '<<r<<endl;
	int i=mid+1,j=l;
	while(i<=r)
	{
		// cerr<<">"<<i<<' '<<j<<endl;
		while(j<=mid && b[j].b<=b[i].b)
		{
			add(b[j].c,b[j].cnt);
			++j;
		}
		b[i].ans+=qry(b[i].c);//注意这里
		i++;
	}
	For(id,l,j-1) add(b[id].c,-b[id].cnt);
}
signed main()
{
	read(n,k);
	For(i,1,n) read(a[i].a,a[i].b,a[i].c);
	sort(a+1,a+1+n,cmp1);
	b[1]=a[1];b[1].cnt=1;
	For(i,2,n)
	{
		if(a[i].a==a[i-1].a && a[i].b==a[i-1].b && a[i].c==a[i-1].c)
		{
			b[tot].cnt++;
		}
		else
		{
			b[++tot]=a[i];
			b[tot].cnt=1;
		}
	}//去重
	solve(1,tot);
	For(i,1,tot)
	{
		final[b[i].ans+b[i].cnt-1]+=b[i].cnt;//注意这里
	}
	For(i,0,n-1) cout<<final[i]<<endl;
	return 0;
}

按照我的个人理解,ii 下标无论对应的是结构体元素还是一个新的数组,答案不是一样的吗(

求大佬赐教 qwq

2022/8/12 22:15
加载中...