• SPOJ 375 query on a tree 树链剖分


    题意:

    给一棵树型数据结构

    ①支持修改边的权值      ②支持成段边权最值查询

    树链剖分入门题、

    树链剖分+线段树

    用的notonlysuccess的线段树——不开结构体事先预处理的那种

    我以前写的都是结构体的那种~

    View Code
      1 #include <iostream>
      2 #include <algorithm>
      3 #include <cstdlib>
      4 #include <cstdio>
      5 #include <cstring>
      6 
      7 //notonlysuccess版线段树-树链剖分 
      8 
      9 #define N 20010
     10 
     11 using namespace std;
     12 
     13 int d[N][3];
     14 int to[N<<1],next[N<<1];
     15 int mx[N];
     16 int root,tot,cnt,n,m,cas;
     17 int head[N],dep[N],wnum[N],fa[N],top[N],son[N],sz[N];
     18 //sz[x]树的大小   dep[x]深度    top[x] x所在重路径中深度最小的点    fa[x]父亲节点   son[x]重儿子   wnum[x] x与其父亲之间的边的编号 
     19 
     20 inline void add(int u,int v)
     21 {
     22     to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++;
     23 }
     24 
     25 inline void dfs(int x)//dfs求出fa[x],son[x],dep[x],sz[x] 
     26 {
     27     sz[x]=1; son[x]=0;
     28     for(int i=head[x];~i;i=next[i])
     29         if(fa[x]!=to[i])
     30         {
     31             fa[to[i]]=x;
     32             dep[to[i]]=dep[x]+1;
     33             dfs(to[i]);
     34             if(sz[to[i]]>sz[son[x]]) son[x]=to[i];//重边
     35             sz[x]+=sz[to[i]];
     36         }
     37 }
     38 
     39 inline void build(int x,int fx)//求出top[x],wnum[x](边的编号) 
     40 {
     41     wnum[x]=++tot; top[x]=fx;
     42     if(son[x]!=0) build(son[x],top[x]);//保证重边边权相连 
     43     for(int i=head[x];~i;i=next[i])
     44         if(to[i]!=son[x]&&to[i]!=fa[x]) build(to[i],to[i]);
     45 }
     46 
     47 inline void updata(int x,int lt,int rt,int wn,int w)
     48 {
     49     if(wn>rt||wn<lt) return;
     50     if(lt==rt) {mx[x]=w; return;}
     51     int mid=(lt+rt)>>1;
     52     int ls=x<<1,rs=ls+1;
     53     updata(ls,lt,mid,wn,w);
     54     updata(rs,mid+1,rt,wn,w);
     55     mx[x]=max(mx[ls],mx[rs]);
     56 }
     57 
     58 inline int maxlen(int x,int lt,int rt,int l,int r)//求边的编号在[l,r]之间的最大边权 
     59 {
     60     if(l>rt||r<lt) return 0;
     61     if(l<=lt&&rt<=r) return mx[x];
     62     int mid=(lt+rt)>>1;
     63     int ls=x<<1,rs=ls+1;
     64     return max(maxlen(ls,lt,mid,l,r),maxlen(rs,mid+1,rt,l,r));
     65 }
     66 
     67 inline int query(int x,int y)
     68 {
     69     int fx=top[x],fy=top[y],ans=0;
     70     while(fx!=fy)
     71     {
     72         if(dep[fx]<dep[fy]) swap(x,y),swap(fx,fy);
     73         ans=max(ans,maxlen(1,1,tot,wnum[fx],wnum[x]));
     74         x=fa[fx]; fx=top[x];
     75     }
     76     if(x==y) return ans;
     77     if(dep[x]>dep[y]) swap(x,y);
     78     return max(ans,maxlen(1,1,tot,wnum[son[x]],wnum[y]));
     79 }
     80 
     81 inline void read()
     82 {
     83     scanf("%d",&n);
     84     root=(n+1)>>1;
     85     fa[root]=dep[root]=cnt=tot=0;
     86     memset(sz,0,sizeof sz);
     87     memset(head,-1,sizeof head);
     88     memset(mx,0,sizeof mx);
     89     for(int i=1;i<n;i++)
     90     {
     91         scanf("%d%d%d",&d[i][0],&d[i][1],&d[i][2]);
     92         add(d[i][0],d[i][1]);
     93         add(d[i][1],d[i][0]);
     94     }
     95     dfs(root);
     96     build(root,root);
     97     for(int i=1;i<n;i++)
     98     {
     99         if(dep[d[i][0]]>dep[d[i][1]]) swap(d[i][0],d[i][1]);
    100         updata(1,1,tot,wnum[d[i][1]],d[i][2]);
    101     }
    102 }
    103 
    104 inline void go()
    105 {
    106     char str[10]; int a,b;
    107     while(true)
    108     {
    109         scanf("%s",str);
    110         if(str[0]=='D') return;
    111         scanf("%d%d",&a,&b);
    112         if(str[0]=='Q') printf("%d\n",query(a,b));
    113         else updata(1,1,tot,wnum[d[a][1]],b);
    114     }
    115 }
    116 
    117 int main()
    118 {
    119     scanf("%d",&cas);
    120     while(cas--) read(),go();
    121     return 0;
    122 } 

    又写了一发,和之前风格完全不同。。

    View Code
      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdlib>
      4 #include <cstdio>
      5 #include <algorithm>
      6 
      7 #define N 100000
      8 #define M 200000
      9 #define INF 1e9
     10 
     11 using namespace std;
     12 
     13 int head[N],next[M],to[M],len[M];
     14 int son[N],fa[N],dat[M],bh[M],pre[N],dep[N],sz[N],top[N];
     15 int q[N],mx[M<<2];
     16 int n,cnt,tot;
     17 
     18 inline void add(int u,int v,int w)
     19 {
     20     to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++;
     21 }
     22 
     23 inline void init()
     24 {
     25     memset(son,-1,sizeof son);
     26     memset(fa,0,sizeof fa);
     27     memset(head,-1,sizeof head); cnt=0;
     28     tot=0;
     29 }
     30 
     31 inline void prep()
     32 {
     33     int h=1,t=2,sta;
     34     q[1]=1; dep[1]=1;
     35     while(h<t)
     36     {
     37         sta=q[h++]; sz[sta]=1;
     38         for(int i=head[sta];~i;i=next[i])
     39             if(fa[sta]!=to[i])
     40             {
     41                 fa[to[i]]=sta;
     42                 dep[to[i]]=dep[sta]+1;
     43                 pre[to[i]]=len[i];
     44                 q[t++]=to[i];
     45             }
     46     }
     47     for(int j=t-1;j>=1;j--)
     48     {
     49         sta=q[j];
     50         for(int i=head[sta];~i;i=next[i])
     51             if(fa[sta]!=to[i])
     52             {
     53                 sz[sta]+=sz[to[i]];
     54                 if(son[sta]==-1||sz[to[i]]>sz[to[son[sta]]]) son[sta]=i;
     55             }
     56     }
     57     for(int i=1;i<t;i++)
     58     {
     59         sta=q[i];
     60         if(to[son[fa[sta]]]==sta) top[sta]=top[fa[sta]];
     61         else top[sta]=sta;
     62     }
     63 }
     64 
     65 inline void rewrite()
     66 {
     67     for(int i=1;i<=n;i++)
     68         if(top[i]==i)
     69             for(int j=son[i];~j;j=son[to[j]])
     70             {
     71                 bh[(j>>1)+1]=++tot;
     72                 dat[tot]=len[i];
     73             }
     74 }
     75 
     76 inline void pushup(int u)
     77 {
     78     mx[u]=max(mx[u<<1],mx[u<<1|1]);
     79 }
     80 
     81 inline void build(int u,int L,int R)
     82 {
     83     if(L==R) {mx[u]=dat[L];return;}
     84     int MID=(L+R)>>1;
     85     build(u<<1,L,MID); build(u<<1|1,MID+1,R);
     86     pushup(u);
     87 }
     88 
     89 inline void read()
     90 {
     91     init();
     92     scanf("%d",&n);
     93     for(int i=1,a,b,c;i<n;i++)
     94     {
     95         scanf("%d%d%d",&a,&b,&c);
     96         add(a,b,c); add(b,a,c);
     97     }
     98     
     99     prep();
    100     rewrite();
    101     build(1,1,tot);
    102 }
    103 
    104 inline void updata(int u,int L,int R,int pos,int sp)
    105 {
    106     if(L==R) {mx[u]=sp;return;}
    107     int MID=(L+R)>>1;
    108     if(pos<=MID) updata(u<<1,L,MID,pos,sp);
    109     else updata(u<<1|1,MID+1,R,pos,sp);
    110     pushup(u);
    111 }
    112 
    113 inline int querymax(int u,int L,int R,int l,int r)
    114 {
    115     if(l<=L&&R<=r) return mx[u];
    116     int MID=(L+R)>>1,res=-INF;
    117     if(l<MID) res=max(res,querymax(u<<1,L,MID,l,r));
    118     if(MID<r) res=max(res,querymax(u<<1|1,MID+1,R,l,r));
    119     return res;
    120 }
    121 
    122 inline int getmax(int x,int y)
    123 {
    124     int res=-INF;
    125     while(top[x]!=top[y])
    126     {
    127         if(dep[top[x]]<dep[top[y]]) swap(x,y);
    128         res=max(res,querymax(1,1,tot,bh[top[x]],bh[x]));
    129         res=max(res,pre[top[x]]);
    130         x=fa[top[x]];
    131     }
    132     if(bh[x]>bh[y]) swap(x,y);
    133     res=max(res,querymax(1,1,tot,bh[x],bh[y]));
    134     return res;
    135 }
    136 
    137 inline void go()
    138 {
    139     char str[10];int a,b;
    140     while(scanf("%s",str))
    141     {
    142         if(str[0]=='D') break;
    143         scanf("%d%d",&a,&b);
    144         if(str[0]=='C') updata(1,1,tot,bh[a],b);
    145         else printf("%d\n",getmax(a,b));
    146     }
    147 }
    148 
    149 int main()
    150 {
    151     int cas;scanf("%d",&cas);
    152     while(cas--) read(),go();
    153     return 0;
    154 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    winform 利用属性在父、子窗体间传值
    .netweb页面间传值的整理
    微软原版sqlhelper
    oracle 实现 split 函数
    sql server通过exec sp_executesql @pagecountsql,N'@RecodeNum int output',@RecodeNum output 传参执行自定义@sql
    .net 对XML实例
    三级联动DropDownList
    Quickly and partly build&debug OOo on ubuntu
    反思
    完整的学习C++的读书路线图
  • 原文地址:https://www.cnblogs.com/proverbs/p/2842572.html
Copyright © 2020-2023  润新知