【解题报告】CF1311F Moving Points

CF1311F Moving Points

最近在做一些真题,然后就发现NOI Online 2022的提高T3是二维偏序,然后我不会二维偏序,来学习一下

题目分析

我们可以把题目分为三种情况

1.\(x_i < x_j\)\(v_i <= v_j\)那目前的距离就是最近的距离

2.\(x_i < x_j\)\(v_i >v_j\),两者会相遇,最近距离为0

3.\(x_j < x_j\)\(v_i > 0,v_j<0\),二者会相遇,最近距离为0

不难看出只有第一种情况会产生贡献

我们用树状数组进行二维偏序

设v小于当前v的节点个数为A

原点到前i个点的距离之和为B

可以推出ans=\(\sum x_i*A-B\)

用两个树状数组维护即可

AC code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#define int long long

using namespace std;

const int maxn=2e5+5;

inline int read()
{
	int w=0,f=1;
	char ch=getchar();
	while(ch<'0' || ch>'9')
	{
		if(ch=='-')
		{
			f=-1;
		}
		ch=getchar();
	}
	while(ch>='0' && ch<='9')
	{
		w=(w<<3)+(w<<1)+(ch^48);
		ch=getchar();
	}
	return w*f;
}

int n,ans;

int b[maxn];

int t[3][maxn];

struct node
{
	int x,v;
}nod[maxn];

bool cmp(node a,node b)
{
	if(a.x!=b.x)
	{
		return a.x<b.x;
	}
	return a.v<b.v;
}

int lowbit(int x)
{
	return x&-x;
}

void update(int x,int y,int t[])
{
	for(;x<maxn;x+=lowbit(x))
	{
		t[x]+=y;
	}
}

int query(int x,int t[])
{
	int ans=0;
	for(;x;x-=lowbit(x))
	{
		ans+=t[x];
	}
	return ans;
}

signed main()
{
	n=read();
	
	for(int i=1;i<=n;i++)
	{
		nod[i].x=read();
	}
	
	for(int i=1;i<=n;i++)
	{
		nod[i].v=read();
		b[i]=nod[i].v;
	}
	
	sort(nod+1,nod+n+1,cmp);
	
	sort(b+1,b+n+1);
	
	int num=unique(b+1,b+n+1)-b-1;
	
	for(int i=1;i<=n;i++)
	{
		nod[i].v=lower_bound(b+1,b+num+1,nod[i].v)-b;
	}
	
	for(int i=1;i<=n;i++)
	{
		update(nod[i].v,nod[i].x,t[1]);
		update(nod[i].v,1,t[2]);
		ans+=nod[i].x*query(nod[i].v,t[2])-query(nod[i].v,t[1]);
	}
	
	cout<<ans;
	
	return 0;
}
posted @ 2022-09-25 20:16  NinT_W  阅读(15)  评论(0编辑  收藏  举报