CF1311F Moving Points
思路
给出一种不需要脑子的四颗树状数组解法。
这四颗树状数组分别为:一颗维护负数,一颗维护负数个数,一颗维护正数,一颗维护正数个数。
首先考虑没有速度该怎么求。
不妨先按
接下来考虑加入速度。
我们只需考虑两种情况:相遇和相离,由于时间无限,所以相遇的情况
我们已经把所有的
设当前扫到的位置为
- 若
,则此时能与 距离为 的点 必定满足 ,这是简单的追及问题。 - 若
,则此时能与 距离为 的点 必定满足 或 , 是相遇问题, 是追及问题。
接下来就可以简单地二维数点了,或者也可以像我一样暴力开四颗树状数组维护。
代码
//A tree without skin will surely die.
//A man without face is invincible.
#include<bits/stdc++.h>
using namespace std;
#define int long long
int const N=2e5+10;
int n,b[N],sum[N],hsum[N];
struct node{int x,v;}a[N];
struct Tree_Array{
int c[N];
#define lowbit(x) (x&-x)
inline void update(int x,int v){while (x<=n) c[x]+=v,x+=lowbit(x);}
inline int query(int x){int res=0;while (x) res+=c[x],x-=lowbit(x);return res;}
}T[5];
inline bool cmp(node a,node b){return a.x<b.x;}
signed main(){
//读入
sort(b+1,b+n+1);int l=unique(b+1,b+n+1)-b-1;//离散化
for (int i=1;i<=n;++i) a[i].v=lower_bound(b+1,b+l+1,a[i].v)-b;
sort(a+1,a+n+1,cmp);int ans=0;
for (int i=1;i<=n;++i) sum[i]=sum[i-1]+a[i].x;
for (int i=n;i>=1;--i) hsum[i]=hsum[i+1]+a[i].x;
for (int i=1;i<=n;++i) ans+=a[i].x*(i-1)-sum[i-1];
int sum0=0,sum=0;
for (int i=1;i<=n;i=i){
int j=i;while (a[j+1].x==a[i].x) ++j;
for (int k=i;k<=j;++k){
if (!b[a[k].v]){
ans-=a[k].x*T[3].query(n)-T[0].query(n);
continue;
}
if (b[a[k].v]>0) ans-=a[k].x*(T[3].query(n)-T[3].query(a[k].v))-(T[0].query(n)-T[0].query(a[k].v));
else ans-=a[k].x*sum0-sum+a[k].x*(T[3].query(n)+(T[4].query(n)-T[4].query(a[k].v)))-(T[0].query(n)+(T[1].query(n)-T[1].query(a[k].v)));
}
for (int k=i;k<=j;++k){
if (!b[a[k].v]){
++sum0;
sum+=a[k].x;
continue;
}
if (b[a[k].v]>0) T[0].update(a[k].v,a[k].x),T[3].update(a[k].v,1);
else T[1].update(a[k].v,a[k].x),T[4].update(a[k].v,1);
}
i=j+1;
}
//输出
return 0;
}
本文作者:Tx_Lcy
本文链接:https://www.cnblogs.com/tx-lcy/p/16810144.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
标签:
做题笔记
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步