• hdu6110:路径交


    $n leq 500000$的树给$m leq 500000$个路径,$q leq 500000$个询问每次问一个区间的路径交。

    路径交口诀:(前方高能)

    判有交,此链有彼祖;

    取其交,最深两两祖。

    说成人话就是:判两条路径有没有交,只要一条链的lca在另一条链上就一定有交;取两条路径的交,把两条路径的端点两两求出四对lca,最深那两个就是路径交。

    证明?我会还用口诀!

    由于需要很多很多次查lca,这里用欧拉序+st表求。查区间路径交可以线段树也可以st表,毕竟重复的部分算两次没问题。

      1 //#include<iostream>
      2 #include<cstring>
      3 #include<cstdlib>
      4 #include<cstdio>
      5 //#include<time.h>
      6 //#include<complex>
      7 #include<algorithm>
      8 #include<stdlib.h>
      9 using namespace std;
     10 
     11 int n,m,q;
     12 #define maxn 500011
     13 struct Edge{int to,next,v;}edge[maxn<<1]; int first[maxn],le=2;
     14 void in(int x,int y,int v) {Edge &e=edge[le]; e.to=y; e.v=v; e.next=first[x]; first[x]=le++;}
     15 void insert(int x,int y,int v) {in(x,y,v); in(y,x,v);}
     16 
     17 int len,dep[maxn],id[maxn],st[maxn<<1][22],Log[maxn<<1];
     18 #define LL long long
     19 LL dis[maxn];
     20 void dfs(int x,int fa)
     21 {
     22     st[++len][0]=x; id[x]=len; dep[x]=dep[fa]+1;
     23     for (int i=first[x];i;i=edge[i].next)
     24     {
     25         Edge &e=edge[i]; if (e.to==fa) continue;
     26         dis[e.to]=dis[x]+e.v; dfs(e.to,x); st[++len][0]=x;
     27     }
     28 }
     29 
     30 void makest()
     31 {
     32     Log[0]=-1; for (int i=1;i<=len;i++) Log[i]=Log[i>>1]+1;
     33     for (int j=1;j<=20;j++)
     34         for (int i=1,to=len-(1<<j)+1;i<=to;i++)
     35             st[i][j]=dep[st[i][j-1]]<dep[st[i+(1<<(j-1))][j-1]]?st[i][j-1]:st[i+(1<<(j-1))][j-1];
     36 }
     37 
     38 int lca(int x,int y)
     39 {
     40     if (id[x]>id[y]) {int t=x;x=y;y=t;} x=id[x]; y=id[y];
     41     int l=Log[y-x+1];
     42     return dep[st[x][l]]<dep[st[y-(1<<l)+1][l]]?st[x][l]:st[y-(1<<l)+1][l];
     43 }
     44 
     45 struct Line{int x,y;}line[maxn];
     46 bool cmpdep(const int a,const int b) {return dep[a]<dep[b];} 
     47 Line combine(Line a,Line b)
     48 {
     49     if (a.x==-1 || b.x==-1) return (Line){-1,-1};
     50     int l1=lca(a.x,a.y),l2=lca(b.x,b.y);
     51     int t1=lca(l1,b.x),t2=lca(l1,b.y),t3=lca(a.x,l2),t4=lca(a.y,l2);
     52     bool flag=0;
     53     if ((t1==l1 && dep[t1]>=dep[l2]) || (t2==l1 && dep[t2]>=dep[l2])) flag=1;
     54     if ((t3==l2 && dep[t3]>=dep[l1]) || (t4==l2 && dep[t4]>=dep[l1])) flag=1;
     55     if (!flag) return (Line){-1,-1};
     56     int d[5]; d[0]=lca(a.x,b.x); d[1]=lca(a.x,b.y); d[2]=lca(a.y,b.x); d[3]=lca(a.y,b.y);
     57     sort(d,d+4,cmpdep); return (Line){d[2],d[3]};
     58 }
     59 
     60 struct SMT
     61 {
     62     struct Node
     63     {
     64         int ls,rs;
     65         Line com;
     66     }a[maxn<<1];
     67     int size,n;
     68     void clear(int m) {size=0; n=m;}
     69     void up(int x)
     70     {
     71         int &p=a[x].ls,&q=a[x].rs;
     72         a[x].com=combine(a[p].com,a[q].com);
     73     }
     74     void build(int &x,int L,int R)
     75     {
     76         x=++size;
     77         if (L==R) {a[x].com=line[L]; a[x].ls=a[x].rs=0; return;}
     78         int mid=(L+R)>>1;
     79         build(a[x].ls,L,mid); build(a[x].rs,mid+1,R); up(x);
     80     }
     81     void build() {int x; build(x,1,n);}
     82     int ql,qr;
     83     Line Query(int x,int L,int R)
     84     {
     85         if (ql<=L && R<=qr) return a[x].com;
     86         int mid=(L+R)>>1; Line ans; bool flag=0;
     87         if (ql<=mid) ans=Query(a[x].ls,L,mid),flag=1;
     88         if (qr>mid) {if (flag) ans=combine(Query(a[x].rs,mid+1,R),ans); else ans=Query(a[x].rs,mid+1,R);}
     89         return ans;
     90     }
     91     Line query(int L,int R) {ql=L; qr=R; return Query(1,1,n);}
     92 }t;
     93 
     94 int main()
     95 {
     96     scanf("%d",&n);
     97     for (int i=1,x,y,v;i<n;i++) scanf("%d%d%d",&x,&y,&v),insert(x,y,v);
     98     len=0; dfs(1,0); makest();
     99     scanf("%d",&m);
    100     for (int i=1;i<=m;i++) scanf("%d%d",&line[i].x,&line[i].y);
    101     t.clear(m); t.build();
    102     scanf("%d",&q);
    103     while (q--)
    104     {
    105         int x,y; scanf("%d%d",&x,&y);
    106         Line ans=t.query(x,y);
    107         printf("%lld
    ",dis[ans.x]+dis[ans.y]-2*dis[lca(ans.x,ans.y)]);
    108     }
    109     return 0;
    110 }
    View Code
  • 相关阅读:
    OpenStack local.conf
    Murano Weekly Meeting 2015.07.21
    Python package和folder
    WSGI学习系列eventlet.wsgi
    OpenStack Weekly Rank 2015.07.20
    Eventlet Greenlet
    OpenStack Weekly Meeting 2015.07.17
    OpenStack创建实例错误解决方法
    Linux Shell命令系列(5) VI编辑器
    linux统计使用最多的10个命令
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8564455.html
Copyright © 2020-2023  润新知