zoukankan      html  css  js  c++  java
  • bzoj3083 遥远的国度

      树链剖分,先求出每个点的dfs序区间,查询时假设当前根为x,查询点为y,他们的dfs序分别为[xl,xr],[yl,yr],有三种情况,第一种x=y那么直接输出[1,n]的最小值,第二种这两个区间分离或者[xl,xr]包含[yl,yr],那么直接查询[yl,yr]的最小值,第三种[yl,yr]包含[xl,xr],找到x到y的路径上离y最近的点z,其区间为[zl,zr],那么需要输出min([1,zl-1],[zr+1,n])。

      代码

      1 #include<cstdio>
      2 #include<algorithm>
      3 #define N 2000010
      4 using namespace std;
      5 typedef long long ll;
      6 int dp,pre[N],p[N],tt[N],f[N],gf[N],go[N];
      7 int L[N],R[N],tot,n,m,i,deep[N];
      8 int l[N],r[N],a,b,root,typ;
      9 int jump[110000][19];
     10 ll value[N],e[N],c,v[N],s[N],inf;
     11 void link(int x,int y)
     12 {
     13     dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y;
     14 }
     15 void dfs1(int x,int fa)
     16 {
     17     int i;
     18     s[x]=1;f[x]=fa;deep[x]=deep[fa]+1;
     19     jump[x][0]=fa;for (i=1;i<=17;i++) jump[x][i]=jump[jump[x][i-1]][i-1];
     20     i=p[x];
     21     while (i)
     22     {
     23         if (tt[i]!=fa)
     24         {
     25             dfs1(tt[i],x);
     26             s[x]+=s[tt[i]];
     27             if (s[tt[i]]>s[go[x]]) go[x]=tt[i];
     28         }
     29         i=pre[i];
     30     }
     31 }
     32 void dfs2(int x,int Fa,int fa)
     33 {
     34     int i=p[x];
     35     L[x]=++tot;gf[x]=Fa;e[tot]=value[x];
     36     if (go[x]) dfs2(go[x],Fa,x);
     37     while (i)
     38     {
     39         if ((tt[i]!=fa)&&(tt[i]!=go[x]))
     40             dfs2(tt[i],tt[i],x);
     41         i=pre[i];
     42     }
     43     R[x]=tot;
     44 }
     45 void build(int x,int a,int b)
     46 {
     47     l[x]=a;r[x]=b;
     48     if (b-a>1)
     49     {
     50         int m=(l[x]+r[x])>>1;
     51         build(2*x,a,m);
     52         build(2*x+1,m,b);
     53         s[x]=min(s[2*x],s[2*x+1]);
     54     }
     55     else
     56         s[x]=e[b];
     57 }
     58 void clean(int x)
     59 {
     60     if (v[x])
     61     {
     62         s[x]=v[x];
     63         v[2*x]=v[x];
     64         v[2*x+1]=v[x];
     65         v[x]=0;
     66     }
     67 }
     68 void change(int x,int a,int b,ll c)
     69 {
     70     clean(x);
     71     if ((a<=l[x])&&(r[x]<=b))
     72     {
     73         v[x]=c;
     74         return;
     75     }
     76     int m=(l[x]+r[x])>>1;
     77     if (a<m)change(2*x,a,b,c);
     78     if (m<b)change(2*x+1,a,b,c);
     79     clean(2*x);clean(2*x+1);
     80     s[x]=min(s[2*x],s[2*x+1]);
     81 }
     82 ll query(int x,int a,int b)
     83 {
     84     clean(x);
     85     if ((a<=l[x])&&(r[x]<=b))
     86         return s[x];
     87     int m;
     88     ll ans=inf;
     89     m=(l[x]+r[x])>>1;
     90     if (a<m) ans=min(ans,query(2*x,a,b));
     91     if (m<b) ans=min(ans,query(2*x+1,a,b));
     92     return ans;
     93 }
     94 void gao(int a,int b,ll c)
     95 {
     96     while (1)
     97     {
     98         if (gf[a]==gf[b])
     99         {
    100             if (deep[a]<deep[b]) a^=b^=a^=b;
    101             change(1,L[b]-1,L[a],c);
    102             return;
    103         }
    104         else
    105         {
    106             if (deep[gf[a]]<deep[gf[b]]) a^=b^=a^=b;
    107             change(1,L[gf[a]]-1,L[a],c);
    108             a=f[gf[a]];
    109         }
    110     }
    111 }
    112 int find(int x,int y)
    113 {
    114     int i;
    115     for (i=17;i>=0;i--)
    116     if (deep[jump[x][i]]>deep[y]) x=jump[x][i];
    117     return x;
    118 }
    119 int main()
    120 {
    121     inf=1000000000;inf=inf*10;
    122     scanf("%d%d",&n,&m);
    123     for (i=1;i<n;i++)
    124     {
    125         scanf("%d%d",&a,&b);
    126         link(a,b);link(b,a);
    127     }
    128     for (i=1;i<=n;i++)
    129     scanf("%lld",&value[i]);
    130     dfs1(1,0);
    131     dfs2(1,1,0);
    132     build(1,0,n);
    133     scanf("%d",&root);
    134     for (i=1;i<=m;i++)
    135     {
    136         scanf("%d",&typ);
    137         if (typ==1) scanf("%d",&root);
    138         else
    139         if (typ==2)
    140         {
    141             scanf("%d%d%lld",&a,&b,&c);
    142             gao(a,b,c);
    143         }
    144         else
    145         {
    146             scanf("%d",&a);
    147             if (a==root)
    148             printf("%lld
    ",query(1,0,n));
    149             else
    150             if ((L[a]<=L[root])&&(R[root]<=R[a]))
    151             {
    152                 b=find(root,a);
    153                 c=inf;
    154                 if (L[b]-1>0) c=min(c,query(1,0,L[b]-1));
    155                 if (R[b]<n) c=min(c,query(1,R[b],n));
    156                 printf("%lld
    ",c);
    157             }
    158             else
    159             printf("%lld
    ",query(1,L[a]-1,R[a]));
    160         }
    161     }
    162 }
  • 相关阅读:
    delphi point数据类型
    Sql Server 2008 R2链接服务器Oracle数据库
    ORA-28000 账号被锁定的解决办法
    [Oracle] sqlplus / as sysdba ora-01031 insufficient privileges
    Oracle的操作系统认证(/ as sydba 登录方式)
    Delphi使用线程TThread查询数据库
    oracle
    统计字符串中字符出现的次数-Python
    Jmeter保存下载的文件
    如何在Microsoft Store上免费获得 HEIF、HEVC 编码支持
  • 原文地址:https://www.cnblogs.com/fzmh/p/5424972.html
Copyright © 2011-2022 走看看