问题 J: Greedy Termite

Greedy Termite

不是很难,就是写着有点费劲。

#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
typedef long double lf;
typedef pair<int,int>P;
const int inf = 0x7f7f7f7f;
const int N = 1e5+10;
const ll mod = 2012;
const double PI = 3.14;

int read(){
    char ch=getchar();int x=0,f=1;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int random(int n){return(ll)rand()*rand()%n;}

ll x[N],h[N];
ll tree1[N<<5],tree2[N<<5];
ll lazy1[N<<5],lazy2[N<<5];
ll x1,x2;

void pushup(int rt){
    if(tree1[2*rt] > tree1[2*rt+1]){
        tree1[rt] = tree1[2*rt];
        lazy1[rt] = lazy1[2*rt];
    }
    if(tree1[2*rt] < tree1[2*rt+1]){
        tree1[rt] = tree1[2*rt+1];
        lazy1[rt] = lazy1[2*rt+1];
    }
    if(tree1[2*rt] == tree1[2*rt+1]){
        tree1[rt] = tree1[2*rt];
        lazy1[rt] = lazy1[2*rt+1];
    }

    if(tree2[2*rt] > tree2[2*rt+1]){
        tree2[rt] = tree2[2*rt];
        lazy2[rt] = lazy2[2*rt];
    }
    if(tree2[2*rt] < tree2[2*rt+1]){
        tree2[rt] = tree2[2*rt+1];
        lazy2[rt] = lazy2[2*rt+1];
    }
    if(tree2[2*rt] == tree2[2*rt+1]){
        tree2[rt] = tree2[2*rt];
        lazy2[rt] = lazy2[2*rt];
    }
}
void build(int rt,int left,int right){
    if(left == right){
        tree1[rt] = h[left]+x[left];
        lazy1[rt] = x[left];

        tree2[rt] = h[left]-x[left];
        lazy2[rt] = x[left];
        return;
    }
    int mid = (left+right)/2;
    build(2*rt,left,mid);
    build(2*rt+1,mid+1,right);
    pushup(rt);
}
void update(int rt,int left,int right,int k){
    if(left == right){
        tree1[rt] = tree2[rt] = -1e18;
        return;
    }
    int mid = (left+right)/2;
    if(k <= mid) update(2*rt,left,mid,k);
    else update(2*rt+1,mid+1,right,k);
    pushup(rt);
}
ll querytree1(int rt,int left,int right,int l,int r){
    if(left >= l && right <= r){
        return tree1[rt];
    }
    ll cnt = -1e18;
    int mid = (left+right)/2;
    if(l <= mid) cnt = max(cnt,querytree1(2*rt,left,mid,l,r));
    if(r > mid) cnt = max(cnt,querytree1(2*rt+1,mid+1,right,l,r));
    return cnt;
}
ll querytree2(int rt,int left,int right,int l,int r){
    if(left >= l && right <= r){
        return tree2[rt];
    }
    ll cnt = -1e18;
    int mid = (left+right)/2;
    if(l <= mid) cnt = max(cnt,querytree2(2*rt,left,mid,l,r));
    if(r > mid) cnt = max(cnt,querytree2(2*rt+1,mid+1,right,l,r));
    return cnt;
}
void querylazy1(int rt,int left,int right,int l,int r,ll t){
    if(left >= l && right <= r){
        if(tree1[rt] == t){
            x1 = max(x1,lazy1[rt]);
        }
        return;
    }
    int mid = (left+right)/2;
    if(l <= mid) querylazy1(2*rt,left,mid,l,r,t);
    if(r > mid) querylazy1(2*rt+1,mid+1,right,l,r,t);
}
void querylazy2(int rt,int left,int right,int l,int r,ll t){
    if(left >= l && right <= r){
        if(tree2[rt] == t){
            x2 = min(x2,lazy2[rt]);
        }
        return;
    }
    int mid = (left+right)/2;
    if(l <= mid) querylazy2(2*rt,left,mid,l,r,t);
    if(r > mid) querylazy2(2*rt+1,mid+1,right,l,r,t);
}
int main(){
    /*
    /and((unsigned)time(0));
    //freopen("out.txt","w",stdout);
    //freopen("in.txt","r",stdin);\
    */
    int n = read(),root = read();
    for(int i = 1;i <= n;i++){
        x[i] = read();h[i] = read();
    }
    build(1,1,n);
    ll ans = 0;
    for(int i = 1;i < n;i++){
        ll ma1 = -1e18,ma2 = -1e18;

        x1 = -1e18;x2 = 1e18;
        if(root-1 >= 1){
            ma1 = querytree1(1,1,n,1,root-1);
            querylazy1(1,1,n,1,root-1,ma1);
            ma1 -= x[root];
        }
        if(root+1 <= n){
            ma2 = querytree2(1,1,n,root+1,n);
            querylazy2(1,1,n,root+1,n,ma2);
            ma2 += x[root];
        }
        update(1,1,n,root);
        if(ma1 > ma2){
            ans += abs(x[root]-x1);
            root = lower_bound(x+1,x+1+n,x1)-x;
          //  cout<<root<<endl;
        }
        if(ma1 < ma2){
            ans += abs(x[root]-x2);
            root = lower_bound(x+1,x+1+n,x2)-x;
        }
        if(ma1 == ma2){
            if(abs(x[root]-x1) <= abs(x[root]-x2)){
                ans += abs(x[root]-x1);
                root = lower_bound(x+1,x+1+n,x1)-x;
            }else {
                ans += abs(x[root]-x2);
                root = lower_bound(x+1,x+1+n,x2)-x;
            }
        }
    //    cout<<root<<endl;
    }
    cout<<ans<<endl;
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值