zoukankan      html  css  js  c++  java
  • 【LuoguP3038/[USACO11DEC]牧草种植Grass Planting】树链剖分+树状数组【树状数组的区间修改与区间查询】

    模拟题,可以用树链剖分+线段树维护。

    但是学了一个厉害的。。树状数组的区间修改与区间查询。。

    分割线里面的是转载的:

    --------------------------------------------------------------------------------

    [ 3 ]  上面都不是重点……重点是树状数组的区间修改+区间查询 这个很好玩 其实也挺简单

    首先依旧是引入delta数组 delta[i]表示区间 [i, n] 的共同增量 于是修改区间 [l, r] 时修改 delta[l] 和 delta[r + 1] 即可(就是差分的思路)

    查询的时候是查询区间 [l, r] 的和 即sum[r] - sum[l - 1] 所以现在的问题是求sum[i]

     

    1 sum[i] = a[1]+...+a[i] + delta[1]*i + delta[2]*(i - 1) + delta[3]*(i - 2)+...+delta[i]*1   // a[i]为原始数组  
    2        = sigma( a[x] ) + sigma( delta[x]  *  (i + 1 - x) )  
    3        = sigma( a[x] ) + (i + 1) * sigma( delta[x] ) - sigma( delta[x] * x ) 
     

    其中 sigma( a[x] ) 是可以预处理出来的 于是只需要维护 delta[x] 与 delta[x] * x 的前缀和(作为两个树状数组就可以了)

     

    为了试验这个方法我专门去找了之前写线段树挂了好久的例题 = = codevs1082 线段树练习3 

    然后交树状数组的代码是 324ms 内存5M过了 线段树是1027ms 13M 如果去掉读入优化的话代码会更短。

    --------------------------------------------------------------------------------------------------------------------------

    转自:http://blog.csdn.net/qq_21841245/article/details/43956633

    很好。。这题本机测系统暴栈了。。交上去才A。。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<ctime>
      6 #include<queue>
      7 using namespace std;
      8 
      9 const int N=2*100010,S=30,D=20;
     10 struct node{
     11     int x,y,next;
     12 }a[2*N];
     13 struct trnode{
     14     int l,r,lc,rc,d;
     15 }t[2*N];
     16 int n,m,len,num,first[N],dep[N],f[N][S],tot[N],zs[N],dfn[N],top[N],c0[N],c1[N],delta[N];
     17 char s[10];
     18 
     19 void add(int x,int d)
     20 {
     21     for(int i=x;i<=n;i+=(i&(-i))) c0[i]+=d,c1[i]+=d*x;
     22 }
     23 
     24 int getsum(int x)
     25 {
     26     int a0=0,a1=0;
     27     for(int i=x;i>=1;i-=(i&(-i))) a0+=c0[i],a1+=c1[i];
     28     return a0*(x+1)-a1;
     29 }
     30 
     31 
     32 void ins(int x,int y)
     33 {
     34     a[++len].x=x;a[len].y=y;
     35     a[len].next=first[x];first[x]=len;
     36 }
     37 
     38 void dfs(int x,int fa)
     39 {
     40     dep[x]=dep[fa]+1;
     41     f[x][0]=fa;
     42     tot[x]=1;
     43     zs[x]=0;
     44     for(int i=first[x];i;i=a[i].next)
     45     {
     46         int y=a[i].y;
     47         if(y==fa) continue;
     48         dfs(y,x);
     49         tot[x]+=tot[y];
     50         if(zs[x]==0 || tot[y]>tot[zs[x]]) zs[x]=y;
     51     }
     52 }
     53 
     54 void find_top(int x,int fa)
     55 {
     56     dfn[x]=++num;
     57     if(zs[x]) 
     58     {
     59         top[zs[x]]=top[x];
     60         find_top(zs[x],x);
     61     }
     62     for(int i=first[x];i;i=a[i].next)
     63     {
     64         int y=a[i].y;
     65         if(y==fa || y==zs[x]) continue;
     66         top[y]=y;
     67         find_top(y,x);
     68     }
     69 }
     70 
     71 int solve(int x,int y,int tmp)
     72 {
     73     int tx=top[x],ty=top[y],ans=0;
     74     while(tx!=ty)
     75     {
     76         if(dep[tx]<dep[ty]) swap(x,y),swap(tx,ty);
     77         if(tmp==0)
     78         {
     79             add(dfn[tx],1);
     80             add(dfn[x]+1,-1);
     81         }
     82         else ans+=getsum(dfn[x])-getsum(dfn[tx]-1);        
     83         x=f[top[x]][0];tx=top[x];
     84     }
     85     if(x==y) return ans;
     86     else
     87     {
     88         if(dep[x]<dep[y]) swap(x,y);
     89         if(tmp==0)
     90         {
     91             add(dfn[y]+1,1);
     92             add(dfn[x]+1,-1);
     93         }
     94         else ans+=getsum(dfn[x])-getsum(dfn[y]);
     95         return ans;
     96     }
     97 }
     98 
     99 void lca_init()
    100 {
    101     for(int j=1;j<=D;j++)
    102         for(int i=1;i<=n;i++)
    103             f[i][j]=f[f[i][j-1]][j-1];
    104 }
    105 
    106 int lca_query(int x,int y)
    107 {
    108     if(dep[x]<dep[y]) swap(x,y);
    109     for(int i=D;i>=0;i--)
    110     {
    111         if(f[x][i]==0) continue;
    112         if(dep[f[x][i]]>=dep[y]) x=f[x][i];
    113     }
    114     if(x==y) return x;
    115     for(int i=D;i>=0;i--)
    116     {
    117         if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    118     }
    119     return f[x][0];
    120 }
    121 
    122 int main()
    123 {
    124     freopen("a.in","r",stdin);
    125     // freopen("a.out","w",stdout);
    126     // freopen("grassplant.in","r",stdin);
    127     // freopen("grassplant.out","w",stdout);
    128     scanf("%d%d",&n,&m);
    129     int x,y,z;len=0;num=0;
    130     memset(first,0,sizeof(first));
    131     memset(f,0,sizeof(f));
    132     memset(c0,0,sizeof(c0));
    133     memset(c1,0,sizeof(c1));
    134     memset(dep,0,sizeof(dep));
    135     memset(tot,0,sizeof(tot));
    136     memset(zs,0,sizeof(zs));
    137     memset(dfn,0,sizeof(dfn));
    138     for(int i=1;i<n;i++)
    139     {
    140         scanf("%d%d",&x,&y);
    141         ins(x,y);
    142         ins(y,x);
    143     }
    144     dfs(1,0);
    145     top[1]=1;find_top(1,0);
    146     // for(int i=1;i<=n;i++)
    147     // {
    148         // printf("i = %d  dep = %d  zs = %d  tot = %d  dfn = %d  top = %d
    ",i,dep[i],zs[i],tot[i],dfn[i],top[i]);
    149     // }
    150     lca_init();
    151     for(int i=1;i<=m;i++)
    152     {
    153         scanf("%s",s);
    154         scanf("%d%d",&x,&y);
    155         if(s[0]=='P')
    156         {
    157             z=lca_query(x,y);
    158             solve(x,z,0);
    159             solve(y,z,0);
    160         }
    161         else
    162         {
    163             printf("%d
    ",solve(x,y,1));
    164         }
    165     }
    166     return 0;
    167 }
  • 相关阅读:
    redis 基本操作-python 使用redis-手机验证接口-发送短信接口
    登录-注册页面修订
    10-29 课堂笔记
    git 协作开发
    git 常规使用
    luffy-city 基础环境搭建(至轮播图前后台交互实现)-步骤目录
    偏移分页-游标(加密)分页-自定义过滤器-第三方过滤器插件(django-filter)
    drf 大总结
    739. Daily Temperatures
    617. Merge Two Binary Trees
  • 原文地址:https://www.cnblogs.com/KonjakJuruo/p/6021653.html
Copyright © 2011-2022 走看看