Sticey_training#3[MEDIUM]

已补(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 nm[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+wxi
t j = − x j v j + w t_j=\frac{-x_j}{v_j+w} tj=vj+wxj
f ( x ) = t i − t j f(x)=t_i-t_j f(x)=titj
因为保证了 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)=ti1tj1就是一次函数,显然是单调的。
对于每个飞机计算, 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 aibi
则求满足 ( a i − a j ) ( b i − b j ) ≤ 0 (a_i-a_j)(b_i-b_j)\leq0 (aiaj)(bibj)0的对数。
简单的二维偏序,但是要考虑一下等号,因为对 a a a排序,相等的时候我们要算上相等部分的所有。所以干脆对 b b b倒序排,这样保证了之前的 a j ≤ a i a_j\leq a_i ajai,并且相等的时候 b j ≥ b i b_j\geq b_i bjbi,这样就不会少算了

#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;

}

C

D

E

F

G

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值