zoukankan      html  css  js  c++  java
  • bzoj3488: [ONTAK2010]Highways

     


    3488: [ONTAK2010]Highways

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 157  Solved: 23
    [Submit][Status][Discuss]

    Description

    Byteland is a small country, with cities connected by N-1 bidirectional roads. From each city there is just one way of reaching every other city using the road network, which causes severe traffic jams. For this reason several highways have been built; each highway connects some pair of cities. 
    By a route we mean a sequence of roads and/or highways. All cities on a route should be distinct. For each pair of cities x,y there exists exactly one route which does not use any highway; we call such a route the main route between x and y . 
    People going from a city x to a city y can either choose the main route or use some highway. In the latter case the route cannot intersect the main route except for the cities x and  y and must contain exactly one highway. 
    Your task is to calculate the number of routes people can take between given pairs of cities. 

    给一棵n个点的树以及m条额外的双向边
    q次询问,统计满足以下条件的u到v的路径:
    恰经过一条额外的边
    不经过树上u到v的路径上的边

    Input


    The first line of input contains a single integer N(1<=N<=100000) - the number of cities in Byteland. Cities are numbered from 1 to n . Each of the next N -1 lines contains two integers Ai, Bi(1<=Ai,Bi<=N) meaning that cities Ai and Biare connected by a road. 
    The next line contains an integer M(1<=M<=100000) - the number of highways. Each of the next m lines contains a description of a single highway. The next line contains an integer Q (1<=Q<=500000) - the number of queries. Each of the next Q lines contains a description of a query. Both highways and queries are given in the same format as the roads. 

    Output

    Your program should output exactly Q lines. The i-th line should contain the number of routes in the i-th query. 

    Sample Input

    9
    1 2
    2 3
    4 2
    1 5
    5 6
    7 5
    7 8
    9 7
    4
    2 5
    3 4
    6 4
    8 3
    4
    4 9
    2 5
    1 6
    1 7

    Sample Output

    1
    4
    2
    2
     
    题解
    如果询问中u和v不是祖先的关系,这题实际上就是求u的子树中有多少条额外边连到v的子树。如果u是v的祖先,设p是u的孩子,p是v所在的子树,答案就是v的子树中的连的额外边的总数目-v的子树中连的另一端在p中的额外边的数目。
    这样的话我们离线处理。每个节点的线段树是建立在dfs序上,我们自底向上合并,处理到某一个节点时,线段树中一段的值就是这个子树中的所有额外边的另一端连在了这一段上(因为所有子树已经被合并了进来)。这样对于一个询问u,v,在处理到u的时候查询u的线段树中v的子树的一段dfs序的值。如果有祖先关系的话也是差不多处理。
    代码很丑
      1 {$S-}{$I-}{$R-}{$V-}
      2 program j01;
      3 const maxn=100086;maxq=500086;
      4 var head,root:array[0..maxn]of longint;
      5     q,next:array[0..2*maxn]of longint;
      6     q2,next2,id:array[0..maxq]of longint;
      7     head2:array[0..maxn]of longint;
      8     l,r:array[0..40*maxn]of longint;
      9     sum:array[0..40*maxn]of int64;
     10     fir,ed:array[0..maxn]of longint;
     11     ans:array[0..maxq]of int64;
     12     n,m,qu,tt,t2,u,v,i,j,tot,cnt,ll,rr:longint;
     13     fa:array[0..maxn,0..20]of longint;
     14     dep:array[0..maxn]of longint;
     15     dfn:array[0..maxn]of longint;
     16     bin:array[0..maxn]of longint;
     17 
     18 procedure swap(var a,b:longint);inline;
     19 var c:longint;
     20 begin
     21   c:=a;a:=b;b:=c;
     22 end;
     23 
     24 procedure add(const u,v:longint);inline;
     25 begin
     26   inc(tt);q[tt]:=v;next[tt]:=head[u];head[u]:=tt;
     27 end;
     28 
     29 procedure dfs(i,pre:longint);
     30 var j:longint;
     31 begin
     32   for j:=1 to bin[dep[i]] do
     33     fa[i,j]:=fa[fa[i,j-1],j-1];
     34   inc(tot);fir[i]:=tot;
     35   dfn[tot]:=i;
     36   j:=head[i];
     37   while j>0 do
     38   begin
     39     if q[j]<>pre then
     40     begin
     41       dep[q[j]]:=dep[i]+1;fa[q[j],0]:=i;
     42       dfs(q[j],i);
     43     end;
     44     j:=next[j];
     45   end;
     46   ed[i]:=tot;
     47 end;
     48 
     49 procedure ins(var i:longint;ll,rr,ps:Longint);
     50 var mid:longint;
     51 begin
     52   if i=0 then
     53   begin
     54     inc(cnt);i:=cnt;
     55   end;
     56   inc(sum[i]);mid:=(ll+rr)div 2;
     57   if ll=rr then exit;
     58   if ps<=mid then ins(l[i],ll,mid,ps) else ins(r[i],mid+1,rr,ps);
     59 end;
     60 
     61 procedure add2(const u,v,i:longint);inline;
     62 begin
     63   inc(t2);q2[t2]:=v;next2[t2]:=head2[u];id[t2]:=i;head2[u]:=t2;
     64 end;
     65 
     66 function merge(x,y:longint):longint;
     67 begin
     68   if(x=0)or(y=0)then exit(x+y);
     69   sum[x]:=sum[x]+sum[y];
     70   l[x]:=merge(l[x],l[y]);
     71   r[x]:=merge(r[x],r[y]);
     72   exit(x);
     73 end;
     74 
     75 function ask(i,lt,rt:longint):int64;
     76 var mid:longint;
     77 begin
     78   if(ll<=lt)and(rt<=rr) then exit(sum[i]);
     79   mid:=(lt+rt)div 2;ask:=0;
     80   if ll<=mid then ask:=ask(l[i],lt,mid);
     81   if mid+1<=rr then ask:=ask+ask(r[i],mid+1,rt);
     82 end;
     83 
     84 function find(const i,d:longint):longint;inline;
     85 var j,x:longint;
     86 begin
     87   x:=i;
     88   if d=0 then exit(i);
     89   for j:=bin[d] downto 0 do
     90     if d and(1 shl j)>0 then x:=fa[x,j];
     91   exit(x);
     92 end;
     93 
     94 procedure work;
     95 var i,j,k,x:longint;
     96 begin
     97   for x:=tot downto 1 do
     98   begin
     99     i:=dfn[x];
    100     j:=head2[i];
    101     while j>0 do
    102     begin
    103       if (fir[i]<=ed[q2[j]])and(fir[i]>=fir[q2[j]]) then
    104       begin
    105         k:=find(i,dep[i]-dep[q2[j]]-1);
    106         ll:=fir[k];rr:=ed[k];
    107         ans[id[j]]:=sum[root[i]]-ask(root[i],1,n);
    108       end else
    109       begin
    110         ll:=fir[q2[j]];rr:=ed[q2[j]];
    111         ans[id[j]]:=ask(root[i],1,n);
    112       end;
    113       j:=next2[j];
    114     end;
    115     if x<>1 then root[fa[i,0]]:=merge(root[fa[i,0]],root[i]);
    116   end;
    117 end;
    118 
    119 begin
    120   readln(n);
    121   bin[1]:=0;
    122   for i:=2 to n do
    123     if i and(i-1)=0 then bin[i]:=bin[i-1]+1 else bin[i]:=bin[i-1];
    124   fillchar(head,sizeof(head),0);tt:=0;
    125   for i:=1 to n-1 do
    126   begin
    127     readln(u,v);
    128     add(u,v);add(v,u);
    129   end;
    130   tot:=0;dfs(1,0);
    131   readln(m);cnt:=0;
    132   for i:=1 to m do
    133   begin
    134     readln(u,v);
    135     ins(root[u],1,n,fir[v]);ins(root[v],1,n,fir[u]);
    136   end;
    137   readln(qu);
    138   fillchar(head2,sizeof(head2),0);t2:=0;
    139   for i:=1 to qu do
    140   begin
    141     readln(u,v);
    142     if(fir[u]<=fir[v])and(fir[v]<=ed[u])then swap(u,v);
    143     add2(u,v,i);
    144   end;
    145   work;
    146   for i:=1 to qu do
    147   begin
    148     writeln(ans[i]+1);
    149   end;
    150 end.
    View Code
     
  • 相关阅读:
    一本通1281:最长上升子序列 暨 LIS DP求解
    STL初步
    【洛谷P3369】【模板】普通平衡树
    【洛谷P4859】已经没有什么好害怕的了
    【CF961G】Partitions
    【洛谷P4718】【模板】Pollard-Rho算法
    【LOJ#143】质数判定
    【CF917D】Stranger Trees
    【洛谷P3700】小Q的表格
    【洛谷P4245】【模板】任意模数多项式乘法
  • 原文地址:https://www.cnblogs.com/oldjang/p/6591572.html
Copyright © 2011-2022 走看看