zoukankan      html  css  js  c++  java
  • zoj 3724 树状数组经典

    问题:n个点,对于每个点i,都有一条连向i+1的有向边,另外有m条其他的有向边,有q个询问(u,v)求u到v的最短路
     
    将m条有向边和q个询问对所表示的点对一起排序,(u,v)u大的排前,u一样的v小的排前,u和v一样大的先处理插入的再处理询问的;
    边插入边询问;
    树状数组里存的是右端点在v之后的询问的结果的差值
    (1)对于(u,v)u<v的这种边,保证在查询到(u,v)之前,所有的(u2,v2)u<u2<v2<v都已经插入好,同时,(u2,v2) u2<u或者(u2=u && v2>v) 的那些还没插入,树状数组存mat[u1][v1]-(d[v1]-d[u1])的最小值,查询时在加上(d[v]-d[u])
     
    (2)对于(u,v)u>v的这种边,保证在查询到(u,v)之前,所有(u2,v2) v2<v<u<u2的都已经插入好,同时,(u2,v2) v<v2<u2<u那些不能插入。树状数组里存的是mat[u2][v2]+(d[u2]-d[v2]),查询再减去(d[u]-d[v])
     
    所以要通过排序来操作
     
    
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    const int maxn = 100005;
    const int maxm = 200010;
    const int maxt = 200010;
    const LL inf  = (1LL<<60);
    struct node{
        int u,v,kind;
        LL ind;
        bool operator < (node a)const{
            if( u == a.u && v == a.v)return kind < a.kind;
            if( u == a.u)return v < a.v;
            return u > a.u;
        }
    }p[maxn+maxm+maxt];
    LL s[maxn],res[maxt];
    LL b[maxn];
    int n;
    int lowbit(int x){
        return x&(-x);
    }
    void update(int x,LL val){
        while( x <= n){
            b[x] = min(b[x],val);
            x += lowbit(x);
        }
    }
    LL query(int x){
        LL res = inf;
        while( x ){
            res = min(res,b[x]);
            x -= lowbit(x);
        }
        return res;
    }
    
    int main(){
        int i,m;
        while(~scanf("%d %d",&n,&m)){
            for( i = 2; i <= n; i++){
                scanf("%lld",&s[i]);
                s[i] += s[i-1];
            }
            for(i = 0; i < m; i++){
                scanf("%d %d %lld",&p[i].u,&p[i].v,&p[i].ind);
                p[i].kind = 0;
            }
            int t;scanf("%d",&t);
            for( ; i < m+t; i ++){
                scanf("%d %d",&p[i].u,&p[i].v);
                p[i].kind = 1;p[i].ind =i-m;
            }
            sort(p,p+m+t);
          //  for(int i = 0; i < m+t; i++)cout << p[i].u << " " << p[i].v << " " << p[i].ind << " " << p[i].kind << endl;
            memset(b,0,sizeof(b));
            memset(res,0,sizeof(res));//当u == v时距离为0
            for(int i = 0; i < m+t; i++){
                if( p[i].kind == 0 && p[i].u < p[i].v)
                update(p[i].v, p[i].ind - (s[p[i].v] - s[p[i].u]) );
                else if( p[i].kind == 1 && p[i].u < p[i].v)
                res[p[i].ind] = (s[p[i].v] - s[p[i].u]) + query(p[i].v);
            }
            for(int i = 0; i <= n+1;i++)b[i] = inf;
            for(int i = 0; i < m+t; i++){
                if( p[i].kind == 0 && p[i].u > p[i].v)
                update(p[i].v,p[i].ind + (s[p[i].u] - s[p[i].v]));
                else if( p[i].kind == 1 && p[i].u > p[i].v){
                  //  int ans = query(p[i].v);cout << ans << endl;
                    res[p[i].ind] = query(p[i].v) - (s[p[i].u] - s[p[i].v]);
                }
            }
            for(int i = 0; i < t; i++)
            printf("%lld
    ",res[i]);
        }
        return 0;
    }
    /*
    
    5 3
    1 2 3 4
    2 4 2
    1 3 2
    5 1 3
    5
    1 4
    4 2
    3 1
    1 3
    1 5
    
    */
    
     
     
  • 相关阅读:
    Selenium自动化测试-unittest单元测试框架
    Python 面向对象
    【新手总结】在.Net项目中使用Redis作为缓存服务
    asp.net性能优化之使用Redis缓存(入门)
    浅谈MVC、MVP、MVVM架构模式的区别和联系
    jquery uploadify在谷歌浏和火狐下无法上传的解决方案(.Net版)
    [翻译]NUnit---Action Attributes(八)
    [翻译]NUnit---String && Collection && File && Directory Assert (七)
    [翻译]NUnit---Exception && Utility Methods (六)
    [翻译]NUnit---Condition Asserts && Comparisons Asserts && Type Asserts (五)
  • 原文地址:https://www.cnblogs.com/LUO257316/p/3320197.html
Copyright © 2011-2022 走看看