zoukankan      html  css  js  c++  java
  • 模板三连击:树状数组+线段树+主席树

    没事儿干,复习模板......

    1.树状数组

    本来不想写这个的,但是反正就几分钟就打完了,所以就写了,水AC数。

    洛谷 P3374 [模板]树状数组 1

     1 #include<cstdio>
     2 
     3 typedef long long ll;
     4 int n,m;
     5 ll c[500005];
     6 
     7 int lb(int p)
     8 {
     9     return p&(-p);
    10 }
    11 
    12 void add(int p,int v)
    13 {
    14     for(int i=p;i<=n;i+=lb(i))c[i]+=(ll)v;
    15 }
    16 
    17 ll sum(int p)
    18 {
    19     ll ret=0;
    20     for(int i=p;i;i-=lb(i))ret+=c[i];
    21     return ret;
    22 }
    23 
    24 int main()
    25 {
    26     scanf("%d%d",&n,&m);
    27     for(int i=1;i<=n;i++)
    28     {
    29         int t;
    30         scanf("%d",&t);
    31         add(i,t);
    32     }
    33     for(int i=1;i<=m;i++)
    34     {
    35         int op,a,b;
    36         scanf("%d%d%d",&op,&a,&b);
    37         if(op==1)add(a,b);
    38         if(op==2)printf("%lld
    ",sum(b)-sum(a-1));
    39     }
    40     return 0;
    41 }
    树状数组

    2.线段树

    写个既有加法又有乘法的,怕忘了。

    洛谷 P3373 [模板]线段树 2

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 typedef long long ll;
      6 
      7 int n,m,mod;
      8 int lb[400005],rb[400005];
      9 ll sum[400005],lza[400005],lzm[400005];
     10 int bv[100005];
     11 
     12 ll sz(int p)
     13 {
     14     return (ll)(rb[p]-lb[p]+1);
     15 }
     16 
     17 void pushup(int p)
     18 {
     19     sum[p]=(sum[p<<1]+sum[p<<1|1])%mod;
     20 }
     21 
     22 void build(int p,int l,int r)
     23 {
     24     lb[p]=l;rb[p]=r;
     25     lza[p]=0;lzm[p]=1;
     26     if(l==r)
     27     {
     28         sum[p]=(ll)bv[l];
     29         return;
     30     }
     31     int mid=(l+r)>>1;
     32     build(p<<1,l,mid);
     33     build(p<<1|1,mid+1,r);
     34     pushup(p);
     35 }
     36 
     37 void pushdown(int p)
     38 {
     39     if(lza[p]==0&&lzm[p]==1)return;
     40     sum[p<<1]=(sum[p<<1]*lzm[p]%mod+lza[p]*sz(p<<1)%mod)%mod;
     41     sum[p<<1|1]=(sum[p<<1|1]*lzm[p]%mod+lza[p]*sz(p<<1|1)%mod)%mod;
     42     lzm[p<<1]=lzm[p<<1]*lzm[p]%mod;
     43     lzm[p<<1|1]=lzm[p<<1|1]*lzm[p]%mod;
     44     lza[p<<1]=(lza[p<<1]*lzm[p]%mod+lza[p])%mod;
     45     lza[p<<1|1]=(lza[p<<1|1]*lzm[p]%mod+lza[p])%mod;
     46     lza[p]=0;lzm[p]=1;
     47 }
     48 
     49 void add(int p,int l,int r,int v)
     50 {
     51     if(lb[p]>=l&&rb[p]<=r)
     52     {
     53         sum[p]=(sum[p]+(sz(p)*(ll)v)%mod)%mod;
     54         lza[p]=(lza[p]+v)%mod;
     55         return;
     56     }
     57     pushdown(p);
     58     int mid=(lb[p]+rb[p])>>1;
     59     if(l<=mid)add(p<<1,l,r,v);
     60     if(r>mid)add(p<<1|1,l,r,v);
     61     pushup(p);
     62 }
     63 
     64 void mul(int p,int l,int r,int v)
     65 {
     66     if(lb[p]>=l&&rb[p]<=r)
     67     {
     68         sum[p]=sum[p]*(ll)v%mod;
     69         lzm[p]=lzm[p]*(ll)v%mod;
     70         lza[p]=lza[p]*(ll)v%mod;
     71         return;
     72     }
     73     pushdown(p);
     74     int mid=(lb[p]+rb[p])>>1;
     75     if(l<=mid)mul(p<<1,l,r,v);
     76     if(r>mid)mul(p<<1|1,l,r,v);
     77     pushup(p);
     78 }
     79 
     80 ll query(int p,int l,int r)
     81 {
     82     if(lb[p]>=l&&rb[p]<=r)return sum[p];
     83     pushdown(p);
     84     int mid=(lb[p]+rb[p])>>1;
     85     ll ret=0;
     86     if(l<=mid)ret+=query(p<<1,l,r);
     87     if(r>mid)ret+=query(p<<1|1,l,r);
     88     return ret%mod;
     89 }
     90 
     91 int main()
     92 {
     93     scanf("%d%d%d",&n,&m,&mod);
     94     for(int i=1;i<=n;i++)scanf("%d",&bv[i]);
     95     build(1,1,n);
     96     for(int i=1;i<=m;i++)
     97     {
     98         int op;
     99         scanf("%d",&op);
    100         if(op==1)
    101         {
    102             int x,y,k;
    103             scanf("%d%d%d",&x,&y,&k);
    104             mul(1,x,y,k);
    105         }
    106         if(op==2)
    107         {
    108             int x,y,k;
    109             scanf("%d%d%d",&x,&y,&k);
    110             add(1,x,y,k);
    111         }
    112         if(op==3)
    113         {
    114             int x,y;
    115             scanf("%d%d",&x,&y);
    116             ll ans=query(1,x,y);
    117             printf("%lld
    ",ans);
    118         }
    119     }
    120     return 0;
    121 }
    线段树

    还有一道题跟这个几乎一模一样,只是需要先读入初始数组再读入操作数。

    传送门在下面:

    洛谷 P2023 [AHOI2009]维护序列

    3.主席树

     洛谷 P3834 [模板]可持久化线段树 1(主席树)

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 
     6 int n,m;
     7 int rt[200005];
     8 int sum[4000005];
     9 int ls[4000005],rs[4000005],cnt;
    10 int tv[200005];
    11 
    12 struct data
    13 {
    14     int rw,w,id;
    15 }a[200005];
    16 
    17 int cmp(data q,data w)
    18 {
    19     return q.rw<w.rw;
    20 }
    21 
    22 int cmpb(data q,data w)
    23 {
    24     return q.id<w.id;
    25 }
    26 
    27 void edit(int &p,int bef,int l,int r,int v)
    28 {
    29     p=++cnt;
    30     sum[p]=sum[bef]+1;
    31     if(l==r)return;
    32     ls[p]=ls[bef];rs[p]=rs[bef];
    33     int mid=(l+r)>>1;
    34     if(v<=mid)edit(ls[p],ls[bef],l,mid,v);
    35     else edit(rs[p],rs[bef],mid+1,r,v);
    36 }
    37 
    38 int ask(int pl,int pr,int l,int r,int rk)
    39 {
    40     if(l==r)return l;
    41     int mid=(l+r)>>1;
    42     int sz=sum[ls[pr]]-sum[ls[pl]];
    43     if(sz>=rk)return ask(ls[pl],ls[pr],l,mid,rk);
    44     else return ask(rs[pl],rs[pr],mid+1,r,rk-sz);
    45 }
    46 
    47 int main()
    48 {
    49     scanf("%d%d",&n,&m);
    50     for(int i=1;i<=n;i++)scanf("%d",&a[i].rw),a[i].id=i;
    51     sort(a+1,a+n+1,cmp);
    52     a[0].rw=-0x3f3f3f3f;
    53     for(int i=1;i<=n;i++)
    54     {
    55         if(a[i].rw==a[i-1].rw)a[i].w=a[i-1].w;
    56         else a[i].w=a[i-1].w+1,tv[a[i].w]=a[i].rw;
    57     }
    58     sort(a+1,a+n+1,cmpb);
    59     for(int i=1;i<=n;i++)edit(rt[i],rt[i-1],1,n,a[i].w);
    60     for(int i=1;i<=m;i++)
    61     {
    62         int l,r,k;
    63         scanf("%d%d%d",&l,&r,&k);
    64         int ans=ask(rt[l-1],rt[r],1,n,k);
    65         printf("%d
    ",tv[ans]);
    66     }
    67     return 0;
    68 }
    主席树

    离散化的时候,忘把 a[0].rw 赋成-0x3f3f3f3f了,导致WA声一片......

  • 相关阅读:
    centos6安装mono
    Flashcache系统管理员手册
    【ZT】超乎想象 HTML5九大超酷特效体验
    程序员不可不知的C#代码规范
    【推薦】帮你炼成软件架构师的97件事
    [ZT]智能客户端(Smart Client)
    【ZT】成就大型高性能网站的十项规则
    通過SQL取出所有周六/周日的日期到Table
    【杯具】面试才说一句话就被轰出来了
    Integer在webservice的传递
  • 原文地址:https://www.cnblogs.com/cervusy/p/9917103.html
Copyright © 2011-2022 走看看