zoukankan      html  css  js  c++  java
  • 洛谷试炼场 提高模板-nlogn数据结构

    树状数组-区间求和

    P3374 【模板】树状数组 1

     1 /*by SilverN*/
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdio>
     6 #include<cmath>
     7 using namespace std;
     8 int read(){
     9     int x=0,f=1;char ch=getchar();
    10     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    11     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    12     return x*f;
    13 }
    14 const int mxn=500010;
    15 int n,m;
    16 int t[mxn];
    17 void add(int x,int v){
    18     while(x<mxn){t[x]+=v;x+=x&-x;}
    19 }
    20 int smm(int x){
    21     int res=0;
    22     while(x){
    23         res+=t[x];
    24         x-=x&-x;
    25     }
    26     return res;
    27 }
    28 int main(){
    29     int op,x,k;
    30     n=read();m=read();
    31     int i,j;
    32     for(i=1;i<=n;i++){
    33         x=read();
    34         add(i,x);
    35     }
    36     for(i=1;i<=m;i++){
    37         op=read();x=read();k=read();
    38         if(op==1){
    39             add(x,k);
    40         }
    41         else{
    42             printf("%d
    ",smm(k)-smm(x-1));
    43         }
    44     }
    45     return 0;
    46 }
    树状数组1

    树状数组-差分

    P3368 【模板】树状数组 2

     1 /*by SilverN*/
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdio>
     6 #include<cmath>
     7 using namespace std;
     8 int read(){
     9     int x=0,f=1;char ch=getchar();
    10     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    11     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    12     return x*f;
    13 }
    14 const int mxn=500010;
    15 int n,m;
    16 int t[mxn];
    17 void add(int x,int v){
    18     while(x<mxn){t[x]+=v;x+=x&-x;}
    19 }
    20 int smm(int x){
    21     int res=0;
    22     while(x){
    23         res+=t[x];
    24         x-=x&-x;
    25     }
    26     return res;
    27 }
    28 int main(){
    29     int op,x,k;
    30     n=read();m=read();
    31     int i,j;
    32     for(i=1;i<=n;i++){
    33         x=read();
    34         add(i,x);
    35         add(i+1,-x);
    36     }
    37     for(i=1;i<=m;i++){
    38         op=read();
    39         if(op==1){
    40             x=read();k=read();op=read();
    41             add(x,op);
    42             add(k+1,-op);
    43         }
    44         else{
    45             x=read();
    46             printf("%d
    ",smm(x));
    47         }
    48     }
    49     return 0;
    50 }
    树状数组2

    线段树-区间加 区间乘

    P3373 【模板】线段树 2

      1 /*by SilverN*/
      2 #include<iostream>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<cstdio>
      6 #include<cmath>
      7 #define ls l,mid,rt<<1
      8 #define rs mid+1,r,rt<<1|1
      9 #define lc rt<<1
     10 #define rc rt<<1|1
     11 using namespace std;
     12 const int mxn=1000000;
     13 long long n,p;
     14 long long a[mxn];
     15 struct node{
     16     long long sum;
     17     long long mu;
     18     long long add;
     19 }tr[mxn];
     20 void pushdown(int rt,int m){
     21     tr[lc].sum=(tr[lc].sum*tr[rt].mu+(m-(m>>1))*tr[rt].add)%p;
     22                                 //m-(m>>1)得到区间范围的一半,也就是左子树的范围 
     23     tr[rc].sum=(tr[rc].sum*tr[rt].mu+(m>>1)*tr[rt].add)%p;
     24     tr[lc].mu=tr[lc].mu*tr[rt].mu%p;
     25     tr[rc].mu=tr[rc].mu*tr[rt].mu%p;
     26     tr[lc].add=(tr[lc].add*tr[rt].mu+tr[rt].add)%p;
     27     tr[rc].add=(tr[rc].add*tr[rt].mu+tr[rt].add)%p;
     28     tr[rt].mu=1;tr[rt].add=0;
     29     return;
     30 }
     31 void Build(int l,int r,int rt){
     32     tr[rt].mu=1;tr[rt].add=0;
     33     if(l==r){
     34         tr[rt].sum=a[l];
     35         return;
     36     }
     37     int mid=(l+r)>>1;
     38     Build(ls);
     39     Build(rs);
     40     tr[rt].sum=(tr[rt<<1].sum+tr[rt<<1|1].sum)%p;
     41     return;
     42 }
     43 void add(int L,int R,int l,int r,int rt,int v){
     44     if(L<=l && r<=R){
     45         tr[rt].sum=(tr[rt].sum+v*(r-l+1))%p;//本身值累加区间新增值
     46         tr[rt].add=(tr[rt].add+v)%p;//标记累加 
     47         return; 
     48     }
     49     pushdown(rt,r-l+1);//下传 
     50     int mid=(l+r)>>1;
     51     if(L<=mid)add(L,R,ls,v);
     52     if(R>mid)add(L,R,rs,v);
     53     tr[rt].sum=(tr[lc].sum+tr[rc].sum)%p;
     54     return;
     55 }
     56 void multi(int L,int R,int l,int r,int rt,int v){
     57     if(L<=l && r<=R){
     58         tr[rt].add=(tr[rt].add*v)%p;
     59         tr[rt].mu=(tr[rt].mu*v)%p;
     60         tr[rt].sum=(tr[rt].sum*v)%p;
     61         return;
     62     }
     63     pushdown(rt,r-l+1);
     64     int mid=(l+r)>>1;
     65     if(L<=mid)multi(L,R,ls,v);
     66     if(R>mid)multi(L,R,rs,v);
     67     tr[rt].sum=(tr[lc].sum+tr[rc].sum)%p;
     68     return;
     69 }
     70 long long query(int L,int R,int l,int r,int rt){//查询 
     71     if(L<=l && r<=R)return tr[rt].sum%p;
     72     int mid=(l+r)>>1;
     73     pushdown(rt,r-l+1);
     74     long long res=0;
     75     if(L<=mid)res=(res+query(L,R,ls))%p;
     76     if(R>mid)res=(res+query(L,R,rs))%p;
     77     tr[rt].sum=(tr[lc].sum+tr[rc].sum)%p;
     78     return res%p;
     79 }
     80 int main(){
     81     int M;
     82     scanf("%lld%lld%lld",&n,&M,&p);
     83     int i,j;
     84     for(i=1;i<=n;i++)scanf("%lld",&a[i]);
     85     Build(1,n,1);
     86     int op,g,t,c;
     87     while(M--){
     88         scanf("%d%d%d",&op,&t,&g);
     89         if(op==1){//
     90             scanf("%d",&c);
     91             multi(t,g,1,n,1,c);
     92         }
     93         if(op==2){//
     94             scanf("%d",&c);
     95             add(t,g,1,n,1,c);
     96         }
     97         if(op==3){//询问 
     98             long long ans=query(t,g,1,n,1);
     99             printf("%lld
    ",ans%p);
    100         }
    101     }
    102     return 0;
    103 }
    线段树区间修改

    二叉堆

    P3378 【模板】堆

     1 /*by SilverN*/
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdio>
     6 #include<cmath>
     7 using namespace std;
     8 const int mxn=1200000;
     9 int read(){
    10     int x=0,f=1;char ch=getchar();
    11     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    13     return x*f;
    14 }
    15 int tp[mxn];
    16 int cnt=0;
    17 void add(int x){
    18     tp[++cnt]=x;
    19     int now=cnt;
    20     while(now>1){
    21         int nxt=now/2;
    22         if(tp[nxt]<=tp[now])return;
    23         swap(tp[nxt],tp[now]);
    24         now=nxt;
    25     }
    26     return;
    27 }
    28 int del_head(){
    29     int res=tp[1];
    30     tp[1]=tp[cnt--];
    31     int now=1;
    32     while(now<=cnt/2){
    33         int nxt=now<<1;
    34         if(nxt<cnt && tp[nxt+1]<tp[nxt])nxt++;
    35         if(tp[now]>tp[nxt]){
    36             swap(tp[now],tp[nxt]);
    37             now=nxt;
    38         }
    39         else return res;
    40     }
    41     return res;
    42 }
    43 int main(){
    44     int n;
    45     n=read();
    46     int op,x,y;
    47     int i,j;
    48     for(i=1;i<=n;i++){
    49         op=read();
    50         switch(op){
    51             case 1:{x=read();add(x);break;}
    52             case 2:{printf("%d
    ",tp[1]);break;}
    53             case 3:{del_head();break;}
    54         }
    55     }
    56     return 0;
    57 }
    最小堆

    此处是最小堆

  • 相关阅读:
    接口和抽象类
    TSQL向自增字段中插入值
    字符串驻留备忘
    SQL Like中的逗号分隔符
    TSQL的一点小备忘
    ADO.NET与ADO
    JavaScript Office文档在线编辑备忘
    位运算练习:求多数的大数、二进制数中1的个数
    Vimeo反反复复地重生死亡。
    海底浓烟,低分辨率测试。
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/5910176.html
Copyright © 2011-2022 走看看