已补(2/9)
A
题意
每天可以加一个水位标记,标记可以重合,并且告诉你每天在当前水位上有多少个标记,求每天水位下标记总和。
题解
先求出每天至少多少个,取前缀最值。
但是这样是最少的情况,而且不一定合法,因为每天最多一个。
所以倒过来取
m
a
x
(
a
[
i
+
1
]
−
1
,
a
[
i
]
)
max(a[i+1]-1,a[i])
max(a[i+1]−1,a[i])
得到每天个数之后,
n
−
m
[
i
]
−
1
n-m[i]-1
n−m[i]−1就是当天水位下个数
#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define RFOR(i,a,b) for(int i=a;i>=b;i--)
#define sf(x) scanf("%d",&x)
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 600000+500;
const ll mod = 1e9+7;
int n;
int A[maxn],B[maxn];
int main(){
cin>>n;
int t=0;
FOR(i,1,n)sf(A[i]);
FOR(i,1,n)B[i]=max(B[i-1],A[i]+1);
//FOR(i,1,n)cout<<B[i]<<endl;
RFOR(i,n,1)B[i]=max(B[i+1]-1,B[i]);
//FOR(i,1,n)cout<<B[i]<<endl;
ll ans=0;
FOR(i,1,n){
ans+=B[i]-1-A[i];
}
cout<<ans<<endl;
}
B
题意
告诉你风速范围,告诉你 n n n个飞机方向和速度,求满足存在某个风速能使得两个飞机同时到达 0 0 0的个数,保证都是往 0 0 0飞,速度和位置都带有方向。
题解
x
i
+
(
v
i
+
w
i
)
t
i
=
0
x_i+(v_i+w_i)t_i=0
xi+(vi+wi)ti=0
t
i
=
−
x
i
v
i
+
w
t_i=\frac{-x_i}{v_i+w}
ti=vi+w−xi
t
j
=
−
x
j
v
j
+
w
t_j=\frac{-x_j}{v_j+w}
tj=vj+w−xj
f
(
x
)
=
t
i
−
t
j
f(x)=t_i-t_j
f(x)=ti−tj
因为保证了
w
<
v
j
w<v_j
w<vj,所以分母不会变到
0
0
0。
也就是函数是连续的,求存在
x
∈
[
−
w
,
w
]
x \in [-w,w]
x∈[−w,w],使得
f
(
x
)
=
0
f(x)=0
f(x)=0
充分条件是,
f
(
−
w
)
⋅
f
(
w
)
≤
0
f(-w)·f(w)\leq0
f(−w)⋅f(w)≤0
单调性不易看出。
但是对于
f
(
x
)
=
1
t
i
−
1
t
j
f(x)=\frac{1}{t_i}-\frac{1}{t_j}
f(x)=ti1−tj1就是一次函数,显然是单调的。
对于每个飞机计算,
1
t
(
−
w
)
\frac{1}{t(-w)}
t(−w)1和
1
t
(
w
)
\frac{1}{t(w)}
t(w)1,设为
a
i
、
b
i
a_i、b_i
ai、bi
则求满足
(
a
i
−
a
j
)
(
b
i
−
b
j
)
≤
0
(a_i-a_j)(b_i-b_j)\leq0
(ai−aj)(bi−bj)≤0的对数。
简单的二维偏序,但是要考虑一下等号,因为对
a
a
a排序,相等的时候我们要算上相等部分的所有。所以干脆对
b
b
b倒序排,这样保证了之前的
a
j
≤
a
i
a_j\leq a_i
aj≤ai,并且相等的时候
b
j
≥
b
i
b_j\geq b_i
bj≥bi,这样就不会少算了
#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define RFOR(i,a,b) for(int i=a;i>=b;i--)
#define sf(x) scanf("%d",&x)
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 600000+500;
const ll mod = 1e9+7;
struct node{
int a,b;
friend bool operator < (node x,node y){
if(x.a==y.a)return x.b>y.b;
return x.a<y.a;
}
}A[100050];
int n,m;
double a[100050],b[100050];
vector<pair<double,int> >G;
int C[200050];
const int limit=200005;
int lowbit(int x){return (x&(-x));}
void change(int x,int d){for(int i=x;i<=limit;i+=lowbit(i)){C[i]+=(ll)d;}}
ll query(int x){if(x==0)return 0;ll ret=0;for(int i=x;i;i-=lowbit(i)){ret+=C[i];}return ret;}
int main(){
int n,w;
cin>>n>>w;
FOR(i,1,n){
int x,v;double tmp;sf(x);sf(v);
a[i]=double(v-w)/(-x);
b[i]=double(v+w)/(-x);
G.push_back(make_pair(a[i],2*i-1));
G.push_back(make_pair(b[i],2*i));
}
sort(G.begin(),G.end());
int num=1;
if(G[0].second%2)A[(G[0].second+1)/2].a=num;
else A[G[0].second/2].b=num;
for(int i=1;i<G.size();i++){
if(G[i].first>G[i-1].first)++num;
if(G[i].second%2)A[(G[i].second+1)/2].a=num;
else A[G[i].second/2].b=num;
}
ll ans=0;
memset(C,0,sizeof(C));
sort(A+1,A+1+n);
int now=0;
for(int i=1;i<=n;i++){
ans+=query(limit)-query(A[i].b-1);
change(A[i].b,1);
//cout<<A[i].b-1<<" "<<ans<<endl;
}
cout<<ans<<endl;
}