首页 > 代码库 > 洛谷试炼场 提高模板-nlogn数据结构

洛谷试炼场 提高模板-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\n",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\n",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\n",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\n",tp[1]);break;}53             case 3:{del_head();break;}54         }55     }56     return 0;57 }
最小堆

 

此处是最小堆

洛谷试炼场 提高模板-nlogn数据结构