【解题报告】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;
}