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\n",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

*/
相關文章
相關標籤/搜索