zoukankan      html  css  js  c++  java
  • (离线树链剖分)HDU

    题意:

    一颗树,q次查询从u到v路径上所有权值在l到r之间的和。

    分析:

    一开始想写树上主席树,然后感觉内存不够就放弃。

    然后想了一个小时,然后发现,询问似曾相识,回忆起一题。

    然后发现直接离线搞就行了。

    确切的说这题和HDU4417是完全一样的。

    将询问排序,然后把小的点加进去,然后查询。

    至于l和r,将两个分开分别处理就行了嘛。

    算是比较裸的题了,居然想了这么久。

    (哇,后来发现主席树内存是够的。。

    可以做,与树链第K大类似,一个数组统计区间内的个数,再开一个longlong保存和即可,

    用lca进行二分就行啦。

    这样复杂度才nlogn,比树剖快撒。

    (哇,比赛的时候同学暴力LCA就A了,而且才700+ms,哇

    代码:

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 #include <algorithm>
      5 #include <vector>
      6 
      7 using namespace std;
      8 
      9 const int maxn=100010;
     10 
     11 int n,q,m;
     12 
     13 struct Edge
     14 {
     15     int to,next;
     16 } edge[maxn<<1];
     17 int head[maxn],tot;
     18 int top[maxn];
     19 int fa[maxn];
     20 int deep[maxn];
     21 int num[maxn];
     22 int p[maxn];
     23 int fp[maxn];
     24 int son[maxn];
     25 int pos;
     26 
     27 struct P
     28 {
     29     int val,u;
     30     bool operator<(const P a)const
     31     {
     32         return val<a.val;
     33     }
     34 };
     35 P val[maxn];
     36 
     37 
     38 void addedge(int u,int v)
     39 {
     40     edge[tot].to = v;
     41     edge[tot].next=head[u];
     42     head[u]=tot++;
     43 }
     44 
     45 void dfs1(int u,int pre,int d)
     46 {
     47     deep[u]=d;
     48     fa[u]=pre;
     49     num[u]=1;
     50     for(int i=head[u]; i!=-1; i=edge[i].next)
     51     {
     52         int v = edge[i].to;
     53         if(v!=pre)
     54         {
     55             dfs1(v,u,d+1);
     56             num[u]+=num[v];
     57             if(son[u]==-1||num[v]>num[son[u]])son[u]=v;
     58         }
     59     }
     60 }
     61 
     62 void getpos(int u,int sp)
     63 {
     64     top[u]=sp;
     65     p[u]=pos++;
     66     fp[p[u]]=u;
     67     if(son[u]==-1)return ;
     68     getpos(son[u],sp);
     69     for(int i=head[u]; i!=-1; i=edge[i].next)
     70     {
     71         int v = edge[i].to;
     72         if(v!=son[u]&&v!=fa[u])getpos(v,v);
     73     }
     74 }
     75 
     76 struct Node
     77 {
     78     int left, right;
     79     long long sum;
     80 } node[maxn<<2];
     81 
     82 
     83 void build(int n,int left,int right)
     84 {
     85     node[n].left=left,node[n].right=right;
     86     node[n].sum=0;
     87     if(left==right)return ;
     88     int mid = (left+right)>>1;
     89     build(n<<1,left,mid);
     90     build(n<<1|1,mid+1,right);
     91 }
     92 
     93 void push_up(int n)
     94 {
     95     node[n].sum=node[n<<1].sum+node[n<<1|1].sum;
     96 }
     97 
     98 void update(int n,int pos,long long val)
     99 {
    100     if(node[n].left==node[n].right)
    101     {
    102         node[n].sum+=val;//wait
    103         return ;
    104     }
    105     int mid = (node[n].left+node[n].right)>>1;
    106     if(pos<=mid)update(n<<1,pos,val);
    107     else update(n<<1|1,pos,val);
    108     push_up(n);
    109 }
    110 
    111 long long query(int n,int left,int right)
    112 {
    113     if(left<=node[n].left&&node[n].right<=right)
    114     {
    115         return node[n].sum;
    116     }
    117     int mid = (node[n].left+node[n].right)>>1;
    118     long long sum=0;
    119     if(mid>=left)sum+=query(n<<1,left,right);
    120     if(mid<right)sum+=query(n<<1|1,left,right);
    121     return sum;
    122 }
    123 
    124 
    125 long long findSum(int x,int y)
    126 {
    127     long long tmp = 0;
    128     while(top[x]!=top[y])
    129     {
    130         if(deep[top[x]]<deep[top[y]])swap(x,y);
    131         tmp +=query(1,p[top[x]],p[x]);
    132         x=fa[top[x]];
    133     }
    134     if(deep[x]>deep[y])swap(x,y);
    135     tmp+=query(1,p[x],p[y]);
    136     return tmp;
    137 }
    138 
    139 struct Q
    140 {
    141     int u,v,x;
    142     int i;
    143 };
    144 vector<Q> pl,pr;
    145 
    146 bool cmp(Q a,Q b)
    147 {
    148     return a.x<b.x;
    149 }
    150 
    151 long long ansl[maxn],ansr[maxn];
    152 
    153 
    154 void init()
    155 {
    156     tot=0;
    157     memset(head,-1,sizeof(head));
    158     pos=0;
    159     memset(son,-1,sizeof(son));
    160     pl.clear(),pr.clear();
    161 }
    162 
    163 
    164 int main()
    165 {
    166     while(~scanf("%d%d",&n,&q))
    167     {
    168         init();
    169         for(int i=1; i<=n; i++)
    170         {
    171             scanf("%d",&val[i].val);
    172             val[i].u=i;
    173         }
    174         sort(val+1,val+n+1);
    175         for(int i=0; i<n-1; i++)
    176         {
    177             int u,v;
    178             scanf("%d%d",&u,&v);
    179             addedge(u,v);
    180             addedge(v,u);
    181         }
    182         dfs1(1,0,0);
    183         getpos(1,1);
    184         for(int i=0; i<q; i++)
    185         {
    186             int u,v,a,b;
    187             scanf("%d%d%d%d",&u,&v,&a,&b);
    188             pl.push_back(Q{u,v,a,i});
    189             pr.push_back(Q{u,v,b,i});
    190         }
    191         sort(pl.begin(),pl.end(),cmp);
    192         sort(pr.begin(),pr.end(),cmp);
    193         int l = 1;
    194         build(1,0,pos-1);
    195         for(int i=0; i<pl.size(); i++)
    196         {
    197             while(val[l].val<pl[i].x&&l<=n)
    198             {
    199                 update(1,p[val[l].u],val[l].val);
    200                 l++;
    201             }
    202             ansl[pl[i].i]=findSum(pl[i].u,pl[i].v);
    203         }
    204         build(1,0,pos-1);
    205         l=1;
    206         for(int i=0; i<pr.size(); i++)
    207         {
    208             while(val[l].val<=pr[i].x&&l<=n)
    209             {
    210                 update(1,p[val[l].u],val[l].val);
    211                 l++;
    212             }
    213             ansr[pr[i].i]=findSum(pr[i].u,pr[i].v);
    214         }
    215         for(int i=0;i<q-1;i++){
    216             printf("%lld ",ansr[i]-ansl[i]);
    217         }
    218         printf("%lld
    ",ansr[q-1]-ansl[q-1]);
    219     }
    220     return 0;
    221 }
  • 相关阅读:
    Android之旅十六 android中各种资源的使用
    XTU OJ 1207 Welcome to XTCPC (字符串签到题)
    scala并发编程原生线程Actor、Case Class下的消息传递和偏函数实战
    【云图】怎样设置支付宝里的家乐福全国连锁店地图?
    怎样在QML中使用multitouch
    软件project师周兆熊给IT学子的倾情奉献
    Linux系统下怎样配置SSH?怎样开启SSH?
    数学之路-python计算实战(4)-Lempel-Ziv压缩(2)
    Day5上午解题报告
    一份只有巨佬才能看懂的代码
  • 原文地址:https://www.cnblogs.com/tak-fate/p/7413559.html
Copyright © 2011-2022 走看看