求指出这种方法的错误之处
查看原帖
求指出这种方法的错误之处
122836
World_Creater楼主2022/12/6 20:34

RT\rm RT,我的做法是在 cdq 之前先拆询问,相当于询问:x1x2,y1y1,t1t2x_1\leq x_2,y_1\leq y_1,t_1\leq t_2 (分别表示蓝色,红色,dfs\rm dfs 序)的点的数量并作差分。

但是这样无法通过任何一个点(甚至是样例),但是我也找不出错误点,求大佬指出。

#include<bits/stdc++.h>
using namespace std;
int n,nxt[400005],head[200005],go[400005],k,dfn[200005],l[200005],r[200005],idx,cnt,ans[200005];
void add(int u,int v)
{
	nxt[++k]=head[u];
	head[u]=k;
	go[k]=v;
}
struct query{
	int x,y,t,opt,id,sgn;
	bool operator <(const query &b) const
	{
		return x<b.x;//这里改成三维严格弱序过不了样例。
	}
}a[600005];
struct bit{
	int tree[200005];
	#define lowbit(x) (x&-x)
	void add(int x,int k)
	{
		for(int i=x;i<=n;i+=lowbit(i))
		{
			tree[i]+=k;
		}
	}
	int query(int x)
	{
		int ret=0;
		for(int i=x;i;i^=lowbit(i))
		{
			ret+=tree[i];
		}
		return ret;
	}
}T;
bool cmp(query a,query b)
{
	return a.y<b.y;//这里改成三维严格弱序过不了样例。
}
void cdq(int l,int r)
{
	if(l==r) return ;
	int mid=(l+r)>>1;
	cdq(l,mid);
	cdq(mid+1,r);
	int j=l;
	for(int i=mid+1;i<=r;i++)
	{
		if(a[i].opt==0) continue ;
		for(;j<=mid&&a[j].y<=a[i].y;j++)
		{
			if(a[j].opt==0) T.add(a[j].t,1);
		}
		ans[a[i].id]+=T.query(a[i].t)*a[i].sgn;
	}
	for(int i=l;i<j;i++)
	{
		if(a[i].opt==0) T.add(a[i].t,-1);
	}
	sort(a+l,a+r+1,cmp);
}
void dfs(int x,int fa)
{
	dfn[++idx]=x;
	l[x]=idx;
	for(int i=head[x];i;i=nxt[i])
	{
		int g=go[i];
		if(g!=fa)
		{
			dfs(g,x);
		}
	}
	r[x]=idx;
}
int main()
{
	cin>>n;
	for(int i=1;i<n;i++)
	{
		int u,v;
		cin>>u>>v;
		add(u,v);
		add(v,u);
	}
	dfs(1,0);
	for(int i=1;i<=n;i++)
	{
		int x,y;
		cin>>x>>y;
		a[++cnt]={x,y,l[i],0,0,0};//加入一个点
		a[++cnt]={x,y,l[i],1,i,-1};//拆询问部分
		a[++cnt]={x,y,r[i],1,i,1};
	}
	sort(a+1,a+1+cnt);
	cdq(1,cnt);
	for(int i=1;i<=n;i++)
	{
		if(ans[i]!=0)
		cout<<ans[i]<<"\n";
	}
}
2022/12/6 20:34
加载中...