zoukankan      html  css  js  c++  java
  • [loj3163]动态直径

    直接点分树+线段树,对点分树上每一个节点维护子树内所有点到其的距离,需要支持子树修改(因此要用dfs序+线段树)以及区间最大值查询

    对于查询,先在根节点的线段树中找到距离根节点最远的点,再枚举其与另一个点在点分树上的lca,同时查询区间最大值

    总复杂度为$o(nlog^{2}n)$,会被卡常(惨惨),但支持负边权QAQ

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 200005
      4 #define ll long long
      5 #define L (k<<1)
      6 #define R (L+1)
      7 #define mid (l+r>>1)
      8 struct Edge{
      9     int nex,to;
     10     ll len;
     11 }edge[N<<1];
     12 struct Data{
     13     int n;
     14     map<int,int>dfn,sz,bl;
     15     vector<int>v;
     16     vector<ll>f,tag;
     17     void build(int k,int l,int r){
     18         while (f.size()<=k){
     19             f.push_back(0);
     20             tag.push_back(0);
     21         }
     22         if (l==r)return;
     23         build(L,l,mid);
     24         build(R,mid+1,r);
     25     }
     26     void update(int k,int l,int r,int x,int y,ll z){
     27         if ((l>y)||(x>r))return;
     28         if ((x<=l)&&(r<=y)){
     29             tag[k]+=z,f[k]+=z;
     30             return;
     31         }
     32         update(L,l,mid,x,y,z);
     33         update(R,mid+1,r,x,y,z);
     34         f[k]=max(f[L],f[R])+tag[k];
     35     }
     36     ll query(int k,int l,int r,int x,int y){
     37         if ((l>y)||(x>r))return 0;
     38         if ((x<=l)&&(r<=y))return f[k];
     39         return max(query(L,l,mid,x,y),query(R,mid+1,r,x,y))+tag[k];
     40     }
     41     int find(int k,int l,int r,int x,int y,ll z){
     42         if ((l>y)||(x>r)||(f[k]<z))return 0;
     43         if (l==r)return l;
     44         int ans=find(L,l,mid,x,y,z-tag[k]);
     45         if (ans)return ans;
     46         return find(R,mid+1,r,x,y,z-tag[k]);
     47     }
     48     void update(int x,ll y){
     49         update(1,1,n,dfn[x],dfn[x]+sz[x]-1,y);
     50     }
     51     ll query(int k){
     52         return query(1,1,n,dfn[k],dfn[k]+sz[k]-1);
     53     }
     54     int find(int k){
     55         return v[find(1,1,n,dfn[k],dfn[k]+sz[k]-1,query(k))-1];
     56     }
     57     ll query_one(int k){
     58         return query(1,1,n,dfn[k],dfn[k]);
     59     }
     60     ll query_other(int k){
     61         k=bl[k];
     62         return max(query(1,1,n,1,dfn[k]-1),query(1,1,n,dfn[k]+sz[k],n));
     63     }
     64 }a[N];
     65 int E,n,q,rt,x,y,head[N],sz[N],vis[N],fa[N];
     66 ll w,z,ans;
     67 void add(int x,int y,ll z){
     68     edge[E].nex=head[x];
     69     edge[E].to=y;
     70     edge[E].len=z;
     71     head[x]=E++;
     72 }
     73 void get_sz(int k,int fa){
     74     sz[k]=1;
     75     for(int i=head[k];i!=-1;i=edge[i].nex)
     76         if ((!vis[edge[i].to])&&(edge[i].to!=fa)){
     77             get_sz(edge[i].to,k);
     78             sz[k]+=sz[edge[i].to];
     79         }
     80 }
     81 void get_rt(int k,int fa,int s){
     82     int mx=s-sz[k];
     83     for(int i=head[k];i!=-1;i=edge[i].nex)
     84         if ((!vis[edge[i].to])&&(edge[i].to!=fa)){
     85             get_rt(edge[i].to,k,s);
     86             mx=max(mx,sz[edge[i].to]);
     87         }
     88     if (mx<=s/2)rt=k;
     89 }
     90 void get_data(int k,int fa,int rt,int x){
     91     if (fa==rt)x=k;
     92     a[rt].dfn[k]=++a[rt].n;
     93     a[rt].sz[k]=1;
     94     a[rt].bl[k]=x;
     95     a[rt].v.push_back(k);
     96     for(int i=head[k];i!=-1;i=edge[i].nex)
     97         if ((!vis[edge[i].to])&&(edge[i].to!=fa)){
     98             get_data(edge[i].to,k,rt,x);
     99             a[rt].sz[k]+=a[rt].sz[edge[i].to];
    100         }
    101 }
    102 void dfs(int k,int f){
    103     get_sz(k,0);
    104     get_rt(k,0,sz[k]);
    105     fa[rt]=f;
    106     get_data(rt,0,rt,0);
    107     a[rt].build(1,1,a[rt].n);
    108     vis[rt]=1;
    109     int r=rt;
    110     for(int i=head[rt];i!=-1;i=edge[i].nex)
    111         if (!vis[edge[i].to])dfs(edge[i].to,r);
    112 }
    113 void update(int x,int y,ll z){
    114     if (a[y].dfn[x])swap(x,y);
    115     for(int i=x;i;i=fa[i]){
    116         if (a[i].dfn[x]>a[i].dfn[y])swap(x,y);
    117         a[i].update(y,z);
    118     }
    119 }
    120 ll query(){
    121     int x=a[rt].find(rt);
    122     ll ans=a[x].query(x);
    123     for(int i=x;fa[i];i=fa[i])ans=max(ans,a[fa[i]].query_other(i)+a[fa[i]].query_one(x));
    124     return ans;
    125 }
    126 int main(){
    127     scanf("%d%d%lld",&n,&q,&w);
    128     memset(head,-1,sizeof(head));
    129     for(int i=1;i<n;i++){
    130         scanf("%d%d%lld",&x,&y,&z);
    131         add(x,y,z);
    132         add(y,x,z);
    133     }
    134     dfs(1,0);
    135     for(int i=1;i<=n;i++)
    136         if (!fa[i])rt=i; 
    137     for(int i=0;i<E;i+=2)update(edge[i].to,edge[i^1].to,edge[i].len);
    138     for(int i=1;i<=q;i++){
    139         scanf("%d%lld",&x,&z);
    140         x=(x+ans)%(n-1);
    141         z=(z+ans)%w;
    142         update(edge[x<<1].to,edge[(x<<1)^1].to,z-edge[x<<1].len);
    143         edge[x<<1].len=z;
    144         ans=query();
    145         printf("%lld
    ",ans); 
    146     }
    147     return 0;
    148 } 
    View Code

    我们在每一个点入栈、出栈以及向下搜索时将其加入序列,并记此序列为$a_{i}$,序列长度为$2n-1$

    令$dep_{x}$为$a_{x}$的深度,联系tarjan求lca的结论,不难得到答案即$sum_{1le lle mle r<2n}dep_{l}+dep_{r}-2dep_{m}$

    修改即对$dep_{x}$区间修改,考虑使用线段树维护

    下面,需要用线段树维护这个最大值,考虑先选$m$,那么最大的$dep_{x}$总是会被选的(也可以联系直径的结论,而且这个最大值的位置也是任意的)

    再对于线段树的区间$[l,r]$,来维护$max_{lle xle yle r}dep_{x}-2dep_{y}$和$max_{lle xle yle r}dep_{y}-2dep_{x}$,通过附加维护区间最大值和最小值可以容易的得到

    由此,复杂度为$o(nlog n)$,可以通过

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 100005
      4 #define ll long long
      5 #define oo 2e18
      6 #define L (k<<1)
      7 #define R (L+1)
      8 #define mid (l+r>>1)
      9 struct Edge{
     10     int nex,to;
     11     ll len;
     12 }edge[N<<1];
     13 struct Data{
     14     ll mx,mn,val1,val2,tag;
     15 }f[N<<3];
     16 int E,n,q,x,y,head[N],dfn[N],l[N],r[N],a[N<<1];
     17 ll z,w,ans;
     18 void add(int x,int y,ll z){
     19     edge[E].nex=head[x];
     20     edge[E].to=y;
     21     edge[E].len=z;
     22     head[x]=E++;
     23 }
     24 void dfs(int k,int fa){
     25     dfn[k]=++dfn[0];
     26     l[k]=a[0]+1;
     27     for(int i=head[k];i!=-1;i=edge[i].nex)
     28         if (edge[i].to!=fa){
     29             a[++a[0]]=k;
     30             dfs(edge[i].to,k);
     31         }
     32     a[++a[0]]=k;
     33     r[k]=a[0];
     34 }
     35 Data merge(Data x,Data y){
     36     Data ans;
     37     ans.mx=max(x.mx,y.mx);
     38     ans.mn=min(x.mn,y.mn);
     39     ans.val1=max(max(x.val1,y.val1),x.mx-2*y.mn);
     40     ans.val2=max(max(x.val2,y.val2),y.mx-2*x.mn);
     41     return ans;
     42 }
     43 void upd(int k,ll x){
     44     f[k].tag+=x;
     45     f[k].mx+=x;
     46     f[k].mn+=x;
     47     f[k].val1-=x;
     48     f[k].val2-=x;
     49 }
     50 void down(int k){
     51     upd(L,f[k].tag);
     52     upd(R,f[k].tag);
     53     f[k].tag=0;
     54 }
     55 void build(int k,int l,int r){
     56     f[k]=Data{0,0,0,0,0};
     57     if (l==r)return;
     58     build(L,l,mid);
     59     build(R,mid+1,r);
     60 }
     61 void update(int k,int l,int r,int x,int y,ll z){
     62     if ((l>y)||(x>r))return;
     63     if ((x<=l)&&(r<=y)){
     64         upd(k,z);
     65         return;
     66     }
     67     down(k);
     68     update(L,l,mid,x,y,z);
     69     update(R,mid+1,r,x,y,z);
     70     f[k]=merge(f[L],f[R]);
     71 }
     72 int find(int k,int l,int r){
     73     if (l==r)return l;
     74     down(k);
     75     if (f[k].mx==f[L].mx)return find(L,l,mid);
     76     return find(R,mid+1,r);
     77 }
     78 Data query(int k,int l,int r,int x,int y){
     79     if ((l>y)||(x>r))return f[0];
     80     if ((x<=l)&&(r<=y))return f[k];
     81     down(k);
     82     return merge(query(L,l,mid,x,y),query(R,mid+1,r,x,y));
     83 }
     84 ll query(){
     85     int x=find(1,1,2*n-1);
     86     return query(1,1,2*n-1,x,x).mx+max(query(1,1,2*n-1,1,x).val1,query(1,1,2*n-1,x,2*n-1).val2);
     87 }
     88 int main(){
     89     scanf("%d%d%lld",&n,&q,&w);
     90     memset(head,-1,sizeof(head));
     91     for(int i=1;i<n;i++){
     92         scanf("%d%d%lld",&x,&y,&z);
     93         add(x,y,z);
     94         add(y,x,z);
     95     }
     96     dfs(1,0);
     97     f[0].mn=oo;
     98     f[0].val1=f[0].val2=-oo;
     99     build(1,1,2*n-1);
    100     for(int i=0;i<E;i+=2){
    101         int a=edge[i].to,b=edge[i^1].to;
    102         if (dfn[a]>dfn[b])swap(a,b);
    103         update(1,1,2*n-1,l[b],r[b],edge[i].len);
    104     }
    105     for(int i=1;i<=q;i++){
    106         scanf("%d%lld",&x,&z);
    107         x=(x+ans)%(n-1);
    108         z=(z+ans)%w;
    109         int a=edge[x<<1].to,b=edge[(x<<1)^1].to;
    110         if (dfn[a]>dfn[b])swap(a,b);
    111         update(1,1,2*n-1,l[b],r[b],z-edge[x<<1].len);
    112         edge[x<<1].len=z;
    113         ans=query();
    114         printf("%lld
    ",ans);
    115     }
    116 } 
    View Code
  • 相关阅读:
    51Nod 1007 正整数分组(01背包)
    二叉树层次遍历(以先序输入)
    HttpContext.Current.Request.Url
    SqlDataReader和SqlDataAdapter的区别
    DataSet和DataTable详解
    DataTable和DataSet什么区别
    Git 忽略
    hack速查表
    ie6常见css bug
    详说 IE hasLayout
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14801692.html
Copyright © 2011-2022 走看看