zoukankan      html  css  js  c++  java
  • 洛谷P3676 小清新数据结构题(动态点分治)

    题面在这里>>>

    解题思路:

    开始写了个LCT后来发现是错的QAQ

    正解是动态点分治。

    对于一个点,其答案就是$sum_{i=1}^{n}sum_{i}^{2}$

    很神奇地构造出这个式子$sum_{i=1}^{n}sum_{i}*(Sum_{tot}-sum_{i})$

    其中Sumtot是一棵树的总权值和。

    可以发现它对于一颗树来说是一个定值。

    因为它可以理解成一条边两端选点。

    将它拆开,就变成了$sum_{i=1}^{n}{sum_{i}*Sum_{tot}}-sum_{i=1}^{n}sum_{i}^{2}$

    既然整体是定值,不如在根为1的时候构建,然后维护。

    然后算前面那个东西就好了。

    厉害就厉害在这里,前面那个东西是可以$O(nlog_{2}n)$计算的。

    再来构造一次,这个东西将常数项提出去$Sum_{tot}*{sum_{i=1}^{n}{sum_{i}}}$

    显然那个Sumtot是可以$O(1)$维护的。

    后面那个呢?

    设当前根为$root$

    可以发现对于每一个值产生贡献时在且仅在其父及祖先节点处生效。

    所以一共生效了$mathit{deep_{i}+1}$次

    所以说如果设边权为1那么$deep_{i}={mathit{Dis(i,root)}}$

    那么原式就成为了${sum_{i=1}^{n}{val_{i}}}+{sum_{i=1}^{n}{mathit{Dis(i,root)}}}$

    剩下的部分和幻想乡那道题就一样了。

    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 typedef long long lnt;
      5 const int N=200010;
      6 struct pnt{
      7     int hd;
      8     int fa;
      9     int dp;
     10     int wgt;
     11     lnt val;
     12     lnt sum;
     13     lnt Sum;
     14     int eind;
     15     lnt diss;
     16     lnt disf;
     17     bool vis;
     18 }p[N];
     19 struct ent{
     20     int twd;
     21     int lst;
     22 }e[N<<1];
     23 int rt;
     24 int n,m;
     25 int cnt;
     26 int dfn;
     27 int tdn;
     28 int root;
     29 int size;
     30 int maxsize;
     31 int lg[N<<2];
     32 int eula[N<<2][21];
     33 lnt w;
     34 lnt V;
     35 lnt val[N];
     36 void ade(int f,int t)
     37 {
     38     cnt++;
     39     e[cnt].twd=t;
     40     e[cnt].lst=p[f].hd;
     41     p[f].hd=cnt;
     42     return ;
     43 }
     44 void E_dfs(int x,int f)
     45 {
     46     eula[++dfn][0]=x;
     47     p[x].eind=dfn;
     48     p[x].dp=p[f].dp+1;
     49     for(int i=p[x].hd;i;i=e[i].lst)
     50     {
     51         int to=e[i].twd;
     52         if(to==f)
     53             continue;
     54         E_dfs(to,x);
     55         p[x].wgt+=p[to].wgt;
     56         eula[++dfn][0]=x;
     57     }
     58     return ;
     59 }
     60 void Add_dfs(int x,int f)
     61 {
     62     p[x].Sum=p[x].val;
     63     for(int i=p[x].hd;i;i=e[i].lst)
     64     {
     65         int to=e[i].twd;
     66         if(to==f)
     67             continue;
     68         Add_dfs(to,x);
     69         p[x].Sum+=p[to].Sum;
     70     }
     71     V+=p[x].Sum*(w-p[x].Sum);
     72     return ;
     73 }
     74 int Emin(int x,int y)
     75 {
     76     return p[x].dp<p[y].dp?x:y;
     77 }
     78 int Lca(int x,int y)
     79 {
     80     x=p[x].eind;
     81     y=p[y].eind;
     82     if(x>y)
     83         std::swap(x,y);
     84     int l=lg[y-x+1];
     85     return Emin(eula[x][l],eula[y-(1<<l)+1][l]);
     86 }
     87 int Dis(int x,int y)
     88 {
     89     int z=Lca(x,y);
     90     return p[x].dp+p[y].dp-2*p[z].dp;
     91 }
     92 void grc_dfs(int x,int f)
     93 {
     94     p[x].wgt=1;
     95     int maxs=-1;
     96     for(int i=p[x].hd;i;i=e[i].lst)
     97     {
     98         int to=e[i].twd;
     99         if(to==f||p[to].vis)
    100             continue;
    101         grc_dfs(to,x);
    102         p[x].wgt+=p[to].wgt;
    103         if(maxs<p[to].wgt)
    104             maxs=p[to].wgt;
    105     }
    106     maxs=std::max(maxs,size-p[x].wgt);
    107     if(maxs<maxsize)
    108     {
    109         maxsize=maxs;
    110         root=x;
    111     }
    112     return ;
    113 }
    114 void bin_dfs(int x,int f)
    115 {
    116     p[x].fa=f;
    117     p[x].vis=true;
    118     int tmp=size;
    119     for(int i=p[x].hd;i;i=e[i].lst)
    120     {
    121         int to=e[i].twd;
    122         if(p[to].vis)
    123             continue;
    124         root=0;
    125         if(p[x].wgt<p[to].wgt)
    126             size=tmp-p[x].wgt;
    127         else
    128             size=p[to].wgt;
    129         maxsize=0x3f3f3f3f;
    130         grc_dfs(to,to);
    131         bin_dfs(root,x);
    132     }
    133     return ;
    134 }
    135 void update(int x,lnt y)
    136 {
    137     p[x].sum+=y;
    138     for(int i=x;p[i].fa;i=p[i].fa)
    139     {
    140         lnt tmp=Dis(x,p[i].fa)*y;
    141         p[i].disf+=tmp;
    142         p[p[i].fa].diss+=tmp;
    143         p[p[i].fa].sum+=y;
    144     }
    145     return ;
    146 }
    147 lnt Query(int x)
    148 {
    149     lnt ans=p[x].diss;
    150     for(int i=x;p[i].fa;i=p[i].fa)
    151     {
    152         lnt tmp=Dis(x,p[i].fa);
    153         ans+=p[p[i].fa].diss-p[i].disf;
    154         ans+=tmp*(p[p[i].fa].sum-p[i].sum);
    155     }
    156     return ans;
    157 }
    158 int main()
    159 {
    160     scanf("%d%d",&n,&m);
    161     for(int i=1;i<n;i++)
    162     {
    163         int a,b;
    164         scanf("%d%d",&a,&b);
    165         ade(a,b);
    166         ade(b,a);
    167     }
    168     E_dfs(1,1);
    169     for(int i=2;i<=dfn;i++)
    170         lg[i]=lg[i>>1]+1;
    171     for(int i=1;i<=20;i++)
    172         for(int j=1;j+(1<<i)-1<=dfn;j++)
    173             eula[j][i]=Emin(eula[j][i-1],eula[j+(1<<(i-1))][i-1]);
    174     root=0;
    175     size=n;
    176     maxsize=0x3f3f3f3f;
    177     grc_dfs(1,1);
    178     rt=root;
    179     bin_dfs(root,0);
    180     for(int i=1;i<=n;i++)
    181     {
    182         scanf("%lld",&p[i].val);
    183         update(i,p[i].val);
    184         w+=p[i].val;
    185     }
    186     Add_dfs(1,1);
    187     while(m--)
    188     {
    189         int cmd;
    190         scanf("%d",&cmd);
    191         if(cmd==1)
    192         {
    193             int x,y;
    194             scanf("%d%d",&x,&y);
    195             lnt dv=y-p[x].val;
    196             update(x,dv);
    197             V+=dv*Query(x);
    198             w+=dv;
    199             p[x].val=y;
    200         }else{
    201             int x;
    202             scanf("%d",&x);
    203             lnt ans=-V+w*w;
    204             ans+=Query(x)*w;
    205             printf("%lld
    ",ans);
    206         }
    207     }
    208     return 0;
    209 }
  • 相关阅读:
    HDU
    HDU
    A. Reorder the Array
    A. New Building for SIS Codeforce
    HUD Is It A Tree?!!!!!)
    博客园申请博客批准
    一起学CC3200之CRC校验
    新安装CCS 编译问题Process_begin :createProcess
    一起学CC3200之开发环境简介(2)烧录程序
    新安装CCS 后编译出现问题:gmake:No rule to make target clean
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10160494.html
Copyright © 2011-2022 走看看