zoukankan      html  css  js  c++  java
  • 线段树套线段树

    hdu6800
    
    #include <iostream>
    #include <string.h>
    #include <queue>
    #include <stack>
    #include <map>
    #include <stdio.h>
    #include <algorithm>
    #include <math.h>
    #include <unordered_map>
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> P;
    const int maxn = 1e5 + 10;
    const int maxm=maxn*18+10,maxl=maxm*8+10;
    struct node{
        LL a[4];
        node & operator = (const node &n2)
        {
            a[0]=n2.a[0];
            a[1]=n2.a[1];
            a[2]=n2.a[2];
            a[3]=n2.a[3];
            return *this;
        }
    };
    int pool[maxm],*pool_tail;
    node info[maxl],*info_tail;
    inline void reset()
    {
        pool_tail=pool;
        info_tail=info;
    }
    inline int * ask32(int len)
    {
        int *ret=pool_tail;
        pool_tail+=len;
        return ret;
    }
    inline node * ask256(int len)
    {
        node *ret=info_tail;
        info_tail+=len;
        return ret;
    }
    
    int n,qtot;
    LL dp[maxn];
    P seq[maxn],que[maxn];
    
    inline void upd_min(LL &x,LL y)
    {
        if(x>y)
            x=y;
    }
    inline bool cmp_y(int const &u,int const &v)
    {
        return que[u].second<que[v].second;
    }
    struct Segment{
        int ytot,*yque;
        node *info;
    }seg[maxn<<1|1];
    
    inline int seg_idx(int L,int R)
    {
        return (L+R)|(L<R);
    }
    
    void seg_init_inner(Segment &rt,int L, int R)
    {
        if(L==R)
        {
            return;
            
        }
        int M=(L+R)>>1;
        seg_init_inner(rt, L, M);
        seg_init_inner(rt, M+1, R);
        node *cur=rt.info+seg_idx(L, R);
        node *lft=rt.info+seg_idx(L, M);
        node *rht=rt.info+seg_idx(M+1, R);
        cur->a[0]=min(lft->a[0],rht->a[0]);
        cur->a[1]=min(lft->a[1],rht->a[1]);
        cur->a[2]=min(lft->a[2],rht->a[2]);
        cur->a[3]=min(lft->a[3],rht->a[3]);
        
    }
    void seg_init_outer(int L,int R)
    {
        static int ord[maxn];
        if(L<R)
        {
            int M=(L+R)>>1;
            seg_init_outer(L, M);
            seg_init_outer(M+1, R);
            inplace_merge(ord+L, ord+M+1, ord+R+1, cmp_y);
        }
        else
        {
            ord[L]=L;
        }
        Segment &rt=seg[seg_idx(L, R)];
        rt.ytot=1;
        for(int i=L+1;i<=R;i++)
        {
            rt.ytot+=cmp_y(ord[i-1], ord[i]);
        }
        rt.yque=ask32(rt.ytot);
        rt.info=ask256( 2*rt.ytot-1);
        
        for(int i=L,j=0;i<=R;j++)
        {
            int u=ord[i++],y=que[u].second,xL=que[u].first,xR=xL;
            for(int v;i<=R&&!cmp_y(u, v=ord[i]);i++)
            {
                int tmp=que[v].first;
                if(tmp<xL)
                {
                    xL=tmp;
                }else if(tmp>xR)
                {
                    xR=tmp;
                }
            }
            rt.yque[j]=y;
            node *val=rt.info+(seg_idx(j, j));
            val->a[0]=xL+y;
            val->a[1]=-xR+y;
            val->a[2]=-xR-y;
            val->a[3]=xL-y;
        }
        seg_init_inner(rt, 0, rt.ytot-1);
    }
    inline void seg_update_inner(Segment &rt,int y,node val)
    {
        for(int L=0,R=rt.ytot-1;L<=R;)
        {
            node * cur=rt.info+seg_idx(L, R);
            upd_min(cur->a[0], val.a[0]);
            upd_min(cur->a[1], val.a[1]);
            upd_min(cur->a[2], val.a[2]);
            upd_min(cur->a[3], val.a[3]);
            if(L==R)
                break;
            int M=(L+R)>>1;
            if(y<=rt.yque[M])
                R=M;
            else
                L=M+1;
        }
    }
    inline void seg_update_outer(int pos)
    {
        int x=que[pos].first,y=que[pos].second;
        LL v=dp[pos];
        node val;
        val.a[0]=v+x+y;
        val.a[1]=v-x+y;
        val.a[2]=v-x-y;
        val.a[3]=v+x-y;
        for(int L=0,R=qtot-1;L<=R;)
        {
            seg_update_inner(seg[seg_idx(L, R)], y, val);
            if(L==R)
                break;
            int M=(L+R)>>1;
            if(pos<=M)
                R=M;
            else
                L=M+1;
        }
    }
    
    
    inline LL seg_query_left_inner(Segment &rt, int x, int y) {
        LL ret = LLONG_MAX;
        for(int L = 0, R = rt.ytot - 1; L <= R; ) {
            node *cur = rt.info + seg_idx(L, R);
            
            if(y <= rt.yque[L]) {
                upd_min(ret, cur->a[1] - y);
                break;
            } else if(y >= rt.yque[R]) {
                upd_min(ret, cur->a[2] + y);
                break;
            }
            
            
            int M = (L + R) >> 1;
            if(y <= rt.yque[M]) {
                node *rht = rt.info + seg_idx(M + 1, R);
                upd_min(ret, rht->a[1] - y);
                R = M;
            } else {
                node *lft = rt.info + seg_idx(L, M);
                upd_min(ret, lft->a[2] + y);
                L = M + 1;
            }
            
        }
        if(ret != LLONG_MAX)
            ret += x;
        return ret;
    }
    
    inline LL seg_query_right_inner(Segment &rt, int x, int y) {
        LL ret = LLONG_MAX;
        for(int L = 0, R = rt.ytot - 1; L <= R; ) {
            node *cur = rt.info + seg_idx(L, R);
            if(y <= rt.yque[L]) {
                upd_min(ret, cur->a[0] - y);
                break;
            } else if(y >= rt.yque[R]) {
                upd_min(ret, cur->a[3] + y);
                break;
            }//已经可以确定在哪个象限有答案了
            
            int M = (L + R) >> 1;
            
            if(y <= rt.yque[M]) {
                
                node *rht = rt.info + seg_idx(M + 1, R);
                //在右上方的点的贡献也可以算了
                upd_min(ret, rht->a[0] - y);
                R = M;//从新区间L-M再来
            } else {
                node *lft = rt.info + seg_idx(L, M);
                upd_min(ret, lft->a[3] + y);
                L = M + 1;
            }
        }
        if(ret != LLONG_MAX)
            ret -= x;
        return ret;
    }
    
    inline LL seg_query_outer(int pos) {
        int x = que[pos].first, y = que[pos].second;
        LL ret = dp[pos];
        for(int L = 0, R = qtot - 1; L < R; ) {
            int M = (L + R) >> 1;
            
            if(pos <= M) {
                upd_min(ret, seg_query_right_inner(seg[seg_idx(M + 1, R)], x, y));
                R = M;
            } else {
                upd_min(ret, seg_query_left_inner(seg[seg_idx(L, M)], x, y));
                L = M + 1;
            }
        }
        return ret;
    }
    void solve() {
        scanf("%d", &n);
        for(int i = 0; i < n; ++i) {
            scanf("%d%d", &seq[i].first, &seq[i].second);
            que[i] = seq[i];
            dp[i] = 0;
        }
        sort(que, que + n);
        qtot = unique(que, que + n) - que;
    
        reset();
        seg_init_outer(0, qtot - 1);//线段树初始化
        
    
        LL ans = 0, sum = 0;
            
        int las = lower_bound(que, que + qtot, seq[0]) - que;
        
        for(int i = 1; i < n; ++i) {
            LL adt = abs(seq[i].first - seq[i - 1].first) + abs(seq[i].second - seq[i - 1].second);
            int pos = lower_bound(que, que + qtot, seq[i]) - que;
            LL best = seg_query_outer(pos) - adt;//以换手的代价跑到pos,省了多少的代价
            
            if(dp[las] > best) {//比已经省下的多
                
                ans=min(ans , dp[las] = best );
                
                seg_update_outer(las);
            }
            
            sum += adt;
            las = pos;
        }
        printf("%lld
    ", ans + sum);
    }
    int main() {
        int T;
        scanf("%d", &T);
        for(int Case = 1; Case <= T; ++Case) {
            // printf("Case #%d:
    ", Case);
            solve();
        }
        return 0;
    }
  • 相关阅读:
    [adminitrative][archlinux][setfont] 设置console的字体大小
    [daily][archlinux][rsync] rsync
    [skill][msgpack] 初试msgpack库以及基本使用
    AWS之搭建深度学习主机
    AWS之SSH登录:使用 PuTTY 从 Windows 连接到 Linux 实例
    加拿大大学排名 by USNews
    Python多进程vs多线程
    Python之JSON使用
    Python之模块与包
    Android重打包+重新签名工具Apktool Box
  • 原文地址:https://www.cnblogs.com/King-of-Dark/p/13419856.html
Copyright © 2011-2022 走看看