zoj 树状数组经典 ( 未解)

来源:互联网 发布:黑暗启示录2bt版java 编辑:程序博客网 时间:2024/06/13 09:57
问题: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])
所以要通过排序来操作
[cpp] view plaincopy
  1. #include<iostream>  
  2. #include<cstring>  
  3. #include <cstdio>  
  4. #include <algorithm>  
  5. using namespace std;  
  6. #define ll long long  
  7. ll b[105000];  
  8. int N;  
  9. int lowbit(int x)  
  10. {  
  11.     return x&(-x);  
  12. }  
  13. void upd(int x,ll val)  
  14. {  
  15.     while(x<=N)  
  16.     {  
  17.         b[x]=min(b[x],val);  
  18.         x+=lowbit(x);  
  19.     }  
  20. }  
  21. ll query(int x)  
  22. {  
  23.     ll res=(1LL<<60);  
  24.     while(x)  
  25.     {  
  26.         res=min(res,b[x]);  
  27.         x-=lowbit(x);  
  28.     }  
  29.     return res;  
  30. }  
  31. struct Point  
  32. {  
  33.     int u,v,kind;  
  34.     ll ind;  
  35. }p[400500];  
  36. bool cmp(Point left,Point right)  
  37. {  
  38.     if(left.u==right.u && left.v==right.v)  
  39.         return left.kind<right.kind; // insert before query  
  40.     if(left.u==right.u)  
  41.         return left.v<right.v;  
  42.     return left.u>right.u;  
  43. }  
  44. ll s[100500];  
  45. int ans[200500];  
  46. int main ()  
  47. {  
  48.     int n,m,q,u,v,ind;  
  49.     while(scanf("%d%d",&n,&m)!=EOF)  
  50.     {  
  51.         for(int i=1;i<n;++i)  
  52.         scanf("%d",&ind),s[i+1]=ind+s[i];  
  53.         for(int i=1;i<=m;++i)  
  54.         {  
  55.             scanf("%d%d%lld",&p[i].u,&p[i].v,&p[i].ind);  
  56.             p[i].kind=0;  
  57.         }  
  58.         scanf("%d",&q);  
  59.         for(int i=1;i<=q;++i)  
  60.         {  
  61.             scanf("%d%d",&p[m+i].u,&p[m+i].v);  
  62.             p[m+i].kind=1;  
  63.             p[m+i].ind=i;  
  64.         }  
  65.         sort(p+1,p+1+m+q,cmp);  
  66.         N=n;  
  67.         memset(ans,0,sizeof(ans)); // 一些询问u=v,不初始化都为0,会错  
  68.         memset(b,0,sizeof(b));  
  69.         for(int i=1;i<=m+q;++i)  
  70.         {  
  71.             if(p[i].kind==0 && p[i].u<p[i].v)  
  72.                 upd(p[i].v,p[i].ind-(s[p[i].v]-s[p[i].u]));  
  73.             if(p[i].kind==1 && p[i].u<p[i].v)  
  74.                 ans[p[i].ind]=s[p[i].v]-s[p[i].u]+query(p[i].v);  
  75.         }  
  76.         for(int i=1;i<=n;++i)  
  77.             b[i]=(1LL<<60);  
  78.         for(int i=1;i<=m+q;++i)  
  79.         {  
  80.             if(p[i].kind==0 && p[i].u>p[i].v)  
  81.                 upd(p[i].v,p[i].ind+(s[p[i].u]-s[p[i].v]));  
  82.             if(p[i].kind==1 && p[i].u>p[i].v)  
  83.                 ans[p[i].ind]=query(p[i].v)-(s[p[i].u]-s[p[i].v]);  
  84.         }  
  85.         for(int i=1;i<=q;++i)  
  86.             printf("%d\n",ans[i]);  
  87.     }  
  88.     return 0;  
  89. }  

原创粉丝点击