【模板】【线段树】
1>区间加法+区间和询问
#include<cstdio> #include<cstdlib> #define int long long using namespace std; int n,m; const int N=1e6+3; int d[N]; struct node { int son1,son2; int sum,laz,len; }tr[N<<2]; int root,cnt; void updata(int rt) { int a=tr[rt].son1 ,b=tr[rt].son2 ; tr[rt].sum =tr[a].sum +tr[b].sum ; } void build(int &rt,int l,int r) { rt=++cnt; tr[rt].len =r-l+1; if(l==r) { tr[rt].sum =d[l]; return ; } int mid=(l+r)>>1; build(tr[rt].son1 ,l,mid); build(tr[rt].son2 ,mid+1,r); updata(rt); } void push_down(int rt) { int a=tr[rt].son1 ,b=tr[rt].son2 ,v=tr[rt].laz ; tr[a].laz +=v,tr[b].laz +=v; tr[a].sum +=v*tr[a].len ,tr[b].sum +=v*tr[b].len ; tr[rt].laz =0; } void change(int rt,int l,int r,int ll,int rr,int vv) { if(ll<=l && r<=rr) { tr[rt].laz +=vv,tr[rt].sum +=tr[rt].len *vv; return ; } if(tr[rt].laz ) push_down(rt); int mid=(l+r)>>1; if(rr<=mid) change(tr[rt].son1 ,l,mid,ll,rr,vv); else if(ll>mid) change(tr[rt].son2 ,mid+1,r,ll,rr,vv); else change(tr[rt].son1 ,l,mid,ll,mid,vv),change(tr[rt].son2 ,mid+1,r,mid+1,rr,vv);//有影响??? updata(rt); } int query(int rt,int l,int r,int ll,int rr) { if(ll<=l && r<=rr) return tr[rt].sum ; if(tr[rt].laz ) push_down(rt); int mid=(l+r)>>1; if(rr<=mid) return query(tr[rt].son1 ,l,mid,ll,rr); else if(ll>mid) return query(tr[rt].son2 ,mid+1,r,ll,rr); return query(tr[rt].son1 ,l,mid,ll,rr)+query(tr[rt].son2 ,mid+1,r,ll,rr); } signed main() { scanf("%lld%lld",&n,&m); for(int i=1;i<=n;i++) scanf("%lld",&d[i]); build(root,1,n); int op,ll,rr,vv; while(m--) { scanf("%lld%lld%lld",&op,&ll,&rr); if(op==1) { scanf("%lld",&vv); change(1,1,n,ll,rr,vv); } else printf("%lld\n",query(1,1,n,ll,rr)); } return 0; }
2>区间加法+区间乘法+区间和询问
自设:d[i]*mul +add
#include<cstdio> #include<cstdlib> #define int long long using namespace std; int n,m,mod; const int N=1e5+3; int d[N],root,cnt; struct node { int son1,son2,len; int sum,laz,LAZ; //加,乘两个标记,选择d*LAZ+laz //add时,直接加 //mul时,如果laz!=0,就push_down再乘 //push_down时,如果LAZ!=1 =》 将孩子的laz,LAZ,sum都*mul //再处理laz }tr[N*3]; void updata(int rt) { tr[rt].sum=(tr[tr[rt].son1].sum +tr[tr[rt].son2].sum)%mod; } void build(int &rt,int l,int r) { rt=++cnt; tr[rt].LAZ =1,tr[rt].len =r-l+1; if(l==r) { tr[rt].sum=d[l]%mod; return ; } int mid=(l+r)>>1; build(tr[rt].son1 ,l,mid); build(tr[rt].son2 ,mid+1,r); updata(rt); } void push_down(int rt) { int a=tr[rt].son1 ,b=tr[rt].son2 ; if(tr[rt].LAZ !=1) { int t=tr[rt].LAZ ; tr[a].sum =(tr[a].sum *t)%mod; tr[a].LAZ =(tr[a].LAZ *t)%mod; tr[a].laz =(tr[a].laz *t)%mod; tr[b].sum =(tr[b].sum *t)%mod; tr[b].LAZ =(tr[b].LAZ *t)%mod; tr[b].laz =(tr[b].laz *t)%mod; tr[rt].LAZ =1; } if(tr[rt].laz ) { int t=tr[rt].laz ; tr[a].sum =(tr[a].sum +t*tr[a].len )%mod; tr[a].laz =(tr[a].laz +t)%mod; tr[b].sum =(tr[b].sum +t*tr[b].len )%mod;//写掉了len... tr[b].laz =(tr[b].laz +t)%mod; tr[rt].laz =0; } } void add(int rt,int l,int r,int ql,int qr,int v) { if(ql<=l && r<=qr) { tr[rt].sum =(tr[rt].sum + v*tr[rt].len%mod)%mod; tr[rt].laz =(tr[rt].laz + v)%mod; return ; } push_down(rt); int mid=(l+r)>>1; if(qr<=mid) add(tr[rt].son1 ,l,mid,ql,qr,v); else if(ql>mid) add(tr[rt].son2 ,mid+1,r,ql,qr,v); else add(tr[rt].son1 ,l,mid,ql,mid,v),add(tr[rt].son2 ,mid+1,r,mid+1,qr,v); updata(rt); } void mul(int rt,int l,int r,int ql,int qr,int v) { if(ql<=l && r<=qr) { tr[rt].sum =(tr[rt].sum *v)%mod; tr[rt].laz =(tr[rt].laz *v)%mod; tr[rt].LAZ =(tr[rt].LAZ *v)%mod; return ; } push_down(rt); int mid=(l+r)>>1; if(qr<=mid) mul(tr[rt].son1 ,l,mid,ql,qr,v); else if(ql>mid) mul(tr[rt].son2 ,mid+1,r,ql,qr,v); else mul(tr[rt].son1 ,l,mid,ql,qr,v),mul(tr[rt].son2 ,mid+1,r,ql,qr,v); updata(rt); } int query(int rt,int l,int r,int ql,int qr) { if(ql<=l && r<=qr) return tr[rt].sum ; push_down(rt); int mid=(l+r)>>1; if(qr<=mid) return query(tr[rt].son1 ,l,mid,ql,qr); else if(ql>mid) return query(tr[rt].son2 ,mid+1,r,ql,qr); else return (query(tr[rt].son1 ,l,mid,ql,mid)+query(tr[rt].son2 ,mid+1,r,mid+1,qr))%mod; } signed main() { scanf("%lld%lld%lld",&n,&m,&mod); for(int i=1;i<=n;i++) scanf("%lld",&d[i]); build(root,1,n); int op,x,y,k; for(int i=1;i<=m;i++) { scanf("%lld%lld%lld",&op,&x,&y); if(op==3) printf("%lld\n",query(1,1,n,x,y)); else if(op==1) scanf("%lld",&k),mul(1,1,n,x,y,k%mod); else if(op==2) scanf("%lld",&k),add(1,1,n,x,y,k%mod); } return 0; }
3>离散+统计线段数
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> using namespace std; int n,m; const int N=100003; int op[N][4];//l,r,op,v struct node { int d,id,wz; bool operator < (const node & o) const { return d<o.d; } }d[N*2]; void ls() { scanf("%d %d",&n,&m); char s[10];int l,r,v; for(int i=0;i<m;i++) { scanf("%s %d %d",s,&l,&r); if(l>r) swap(l,r); op[i][0]=l,op[i][1]=r; if(s[0]=='C') scanf("%d",&v),op[i][2]=1,op[i][3]=v; d[i*2].d =l,d[i*2+1].d =r; d[i*2].id =d[i*2+1].id =i; d[i*2].wz =0,d[i*2+1].wz =1; } sort(d,d+2*m); int last=0,w=0; for(int i=0;i<2*m;i++) { if(d[i].d !=last) { w++; if(d[i].d >last+1) w++; last=d[i].d ; op[d[i].id ][d[i].wz ]=w; } else op[d[i].id ][d[i].wz ]=w; } n=w; } int root,tot; struct no { int l,r,lc,rc,col; bool flag;//true为纯色 }tree[N*3]; void updata(int rt) { int lc=tree[rt].lc ,rc=tree[rt].rc ; if(tree[lc ].flag && tree[rc ].flag && tree[lc ].col ==tree[rc ].col ) tree[rt].flag =true,tree[rt].col =tree[lc ].col ; } void create(int &rt,int l,int r) { rt=tot++; tree[rt].l =l,tree[rt].r =r; tree[rt].lc =tree[rt].rc =-1; tree[rt].flag =true; if(l==r) tree[rt].col =1; else { int mid=(l+r)/2; create(tree[rt].lc ,l,mid); create(tree[rt].rc ,mid+1,r); updata(rt); } } void pushdown(int rt) { int lc=tree[rt].lc ,rc=tree[rt].rc ; tree[lc].flag =tree[rc].flag =true; tree[lc].col =tree[rc].col =tree[rt].col ; tree[rt].flag =false; } void change(int rt,int l,int r,int v) { int ll=tree[rt].l ,rr=tree[rt].r; if(l<=ll&&rr<=r) tree[rt].flag =true,tree[rt].col =v; else { if(tree[rt].flag ) pushdown(rt); int mid=(ll+rr)/2; if(r<=mid) change(tree[rt].lc ,l,r,v); else if(l>mid) change(tree[rt].rc ,l,r,v); else change(tree[rt].lc ,l,mid,v), change(tree[rt].rc ,mid+1,r,v); } } bool f[53]; void dfs(int rt,int l,int r) { if(tree[rt].flag ) f[tree[rt].col ]=true; else { int ll=tree[rt].l ,rr=tree[rt].r ; int mid=(ll+rr)/2; if(r<=mid) dfs(tree[rt].lc ,l,r); else if(l>mid) dfs(tree[rt].rc ,l,r); else dfs(tree[rt].lc ,l,mid),dfs(tree[rt].rc ,mid+1,r); } } int main() { ls(); create(root,1,n); for(int i=0;i<m;i++) { if(op[i][2]==1) change(root,op[i][0],op[i][1],op[i][3]); else { memset(f,false,sizeof(f)); dfs(root,op[i][0],op[i][1]); int ans=0; for(int i=0;i<=50;i++) if(f[i]) ans++; printf("%d\n",ans); } } return 0; }