洛谷试炼场 提高模板-nlogn数据结构
Posted SilverNebula
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷试炼场 提高模板-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 }
树状数组-差分
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 }
线段树-区间加 区间乘
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数据结构的主要内容,如果未能解决你的问题,请参考以下文章