4 条题解
-
2
又是一道没有一篇带解释的题解的题
前置知识:线段树
思路
区间修改,单点查询,很明显用线段树做很合适,我们考虑用结构体定义一个节点,包含其覆盖范围,两个懒标记(方便快速计算)。
对于同一个点的先后两次变化和,合并后有,展开得,就得到了新的两个系数。
剩下的就是线段树的事了
AC代码
#include<bits/stdc++.h> #define lc(p) (p<<1) #define rc(p) (p<<1|1) #define int long long using namespace std; const int N=5e5+10,P=998244353; struct node{int l,r,tag,a,b;}tr[N<<2]; int a[N]; void pd(int p) { if(tr[p].tag)//如果带有懒标记 { tr[lc(p)].a=tr[lc(p)].a*tr[p].a%P;tr[rc(p)].a=tr[rc(p)].a*tr[p].a%P;//对新的a的赋值 tr[lc(p)].b=(tr[p].a*tr[lc(p)].b%P+tr[p].b)%P;//对新的b的赋值 tr[rc(p)].b=(tr[p].a*tr[rc(p)].b%P+tr[p].b)%P; tr[lc(p)].tag=tr[rc(p)].tag=1;//子节点也带有标记 tr[p].a=1;tr[p].b=0;tr[p].tag=0;//清空本节点 //a赋值为1是因为a*1+0=a(废话)(很重要!) } } void build(int p,int l,int r)//建线段树 { tr[p]={l,r,0,1,0}; if(l==r)return ; int mid=l+r>>1; build(lc(p),l,mid);build(rc(p),mid+1,r); } void change(int p,int l,int r,int a,int b) { if(tr[p].r<l||r<tr[p].l)return ;//不在目标区域内 if(l<=tr[p].l&&tr[p].r<=r)//被完全覆盖 { tr[p].a=tr[p].a*a%P;tr[p].b=(tr[p].b*a%P+b)%P; tr[p].tag=1; return ; } pd(p);//千万别漏!如果不加会导致两次计算顺序颠倒! change(lc(p),l,r,a,b);change(rc(p),l,r,a,b);//交给儿子去干 } int query(int p,int x) { if(tr[p].r<x||x<tr[p].l)return 0; if(tr[p].l==tr[p].r) { a[x]=(a[x]*tr[p].a%P+tr[p].b)%P;//更新 tr[p].a=1;tr[p].b=0;//清空 return a[x]; } pd(p); return query(lc(p),x)+query(rc(p),x);//统计 } signed main() { int n,q;scanf("%lld%lld",&n,&q); for(int i=0;i<n;i++)scanf("%lld",&a[i]); build(1,0,n-1);//别忘建线段树(别问我怎么知道的) while(q--) { int op,x,y,l,r;scanf("%lld",&op); if(op==0) { scanf("%lld%lld%lld%lld",&l,&r,&x,&y); r--;//根据题意(细节) change(1,l,r,x,y); } else { scanf("%lld",&x); printf("%lld\n",query(1,x)); } } return 0;//完结撒花 }依旧线段树神力
-
0
线段树的一个我认为比较新奇的trick。
记录每个节点的乘数a与加数b,然后一通暴力推导可知若先后对节点进行两次更改与,最终会变成。 然后就跑线段树就可以了。
tips1:节点编号从0到n-1
tips2:lazy更新完要变成(1,0)(x*1+0=x)
带马:
#include<bits/stdc++.h> #define lc(p) (p<<1) #define rc(p) (p<<1|1) #define int long long using namespace std; const int N=5e5+10,mod=998244353; struct node{ int l,r,lazy; int b,c; }tr[N<<2]; int a[N]; void pushdown(int p){ if(tr[p].lazy){ tr[lc(p)].lazy=tr[rc(p)].lazy=1; tr[lc(p)].b=tr[lc(p)].b*tr[p].b%mod; tr[lc(p)].c=(tr[p].b*tr[lc(p)].c%mod+tr[p].c)%mod; tr[rc(p)].b=tr[rc(p)].b*tr[p].b%mod; tr[rc(p)].c=(tr[p].b*tr[rc(p)].c%mod+tr[p].c)%mod; tr[p].b=1;tr[p].c=0;tr[p].lazy=0; } } void build(int p,int l,int r){ tr[p]={l,r,0,1,0}; if(l==r)return; int mid=(l+r)/2; build(lc(p),l,mid);build(rc(p),mid+1,r); } void change(int p,int l,int r,int b,int c){ if(tr[p].r<l||r<tr[p].l)return; if(l<=tr[p].l&&tr[p].r<=r){ tr[p].b=tr[p].b*b%mod;tr[p].c=(tr[p].c*b%mod+c)%mod; tr[p].lazy=1; return; } pushdown(p); change(lc(p),l,r,b,c);change(rc(p),l,r,b,c); } int query(int p,int x){ if(tr[p].r<x||x<tr[p].l)return 0; if(tr[p].l==tr[p].r){ a[x]=(a[x]*tr[p].b%mod+tr[p].c)%mod; tr[p].b=1;tr[p].c=0; return a[x]; } pushdown(p); return query(lc(p),x)+query(rc(p),x); } signed main(){ int n,q;scanf("%lld%lld",&n,&q); for(int i=0;i<n;i++)scanf("%lld",&a[i]); build(1,0,n-1); while(q--){ int op,x,y,l,r;scanf("%lld",&op); if(op==0){ scanf("%lld%lld%lld%lld",&l,&r,&x,&y);r--; change(1,l,r,x,y); } else{ scanf("%lld",&x); printf("%lld\n",query(1,x)); } } return 0; } -
0
#include<bits/stdc++.h> #define lc(p) (p<<1) #define rc(p) (p<<1|1) using namespace std; typedef long long ll; const int mod=998244353; int n,q,a[500010]; struct N{ ll c,k,b; }tr[2000010]; void pushdown(int p,int l,int r){ tr[lc(p)].b=(tr[p].k*tr[lc(p)].b%mod+tr[p].b)%mod; tr[lc(p)].k=tr[lc(p)].k*tr[p].k%mod; tr[rc(p)].b=(tr[p].k*tr[rc(p)].b%mod+tr[p].b)%mod; tr[rc(p)].k=tr[rc(p)].k*tr[p].k%mod; tr[p].k=1; tr[p].b=0; } void bt(int p,int l,int r){ tr[p]={0,1,0}; if(l==r){ tr[p]={a[l],1,0}; return ; } int mid=(l+r)>>1; bt(lc(p),l,mid); bt(rc(p),mid+1,r); } void change(int p,int l,int r,int x,int y,ll k,ll b){ if(l>=x&&r<=y){ tr[p].b=(tr[p].b*k%mod+b)%mod; tr[p].k=tr[p].k*k%mod; return ; } pushdown(p,l,r); int mid=(l+r)>>1; if(x<=mid)change(lc(p),l,mid,x,y,k,b); if(y>mid)change(rc(p),mid+1,r,x,y,k,b); } ll find(int p,int l,int r,int x){ if(l==r)return (tr[p].c*tr[p].k%mod+tr[p].b)%mod; pushdown(p,l,r); int mid=(l+r)>>1; if(x<=mid)return find(lc(p),l,mid,x); else return find(rc(p),mid+1,r,x); } int main(){ ios::sync_with_stdio(0); cin.tie(0); cin>>n>>q; for(int i=1;i<=n;i++)cin>>a[i]; bt(1,1,n); while(q--){ int op; cin>>op; if(op==0){ int l,r,k,b; cin>>l>>r>>k>>b; l++; change(1,1,n,l,r,k,b); } else{ int x; cin>>x; x++; cout<<find(1,1,n,x)<<'\n'; } } return 0; } -
0
#include<bits/stdc++.h> using namespace std; #define int long long const int N=5e5+10,P=998244353; void mod(int &x){x=((x%P)+P)%P;} #define lc(p) (p<<1) #define rc(p) (p<<1|1) struct node{int l,r,s,tag,lazy;}tr[N<<2];int a[N]; void pushup(int p){tr[p].s=tr[lc(p)].s+tr[rc(p)].s;} void pushdown(int p) { if(tr[p].tag!=1) { tr[lc(p)].s*=tr[p].tag;tr[rc(p)].s*=tr[p].tag; mod(tr[lc(p)].s);mod(tr[rc(p)].s); tr[lc(p)].lazy*=tr[p].tag;tr[rc(p)].lazy*=tr[p].tag; mod(tr[lc(p)].lazy);mod(tr[rc(p)].lazy); tr[lc(p)].tag*=tr[p].tag;tr[rc(p)].tag*=tr[p].tag; mod(tr[lc(p)].tag);mod(tr[rc(p)].tag); tr[p].tag=1; } if(tr[p].lazy) { tr[lc(p)].s+=tr[p].lazy*(tr[lc(p)].r-tr[lc(p)].l+1); tr[rc(p)].s+=tr[p].lazy*(tr[rc(p)].r-tr[rc(p)].l+1); mod(tr[lc(p)].s);mod(tr[rc(p)].s); tr[lc(p)].lazy+=tr[p].lazy;tr[rc(p)].lazy+=tr[p].lazy; mod(tr[lc(p)].lazy);mod(tr[rc(p)].lazy); tr[p].lazy=0; } } void bt(int p,int l,int r) { tr[p]={l,r,0,1,0}; if(l==r){tr[p].s=a[l];return;} int mid=(l+r)>>1; bt(lc(p),l,mid);bt(rc(p),mid+1,r); pushup(p); } void change1(int p,int l,int r,int k) { if(tr[p].l>r||tr[p].r<l)return; if(l<=tr[p].l&&tr[p].r<=r) { tr[p].s*=k;tr[p].tag*=k,tr[p].lazy*=k; mod(tr[p].s);mod(tr[p].tag);mod(tr[p].lazy); return ; } pushdown(p); change1(lc(p),l,r,k);change1(rc(p),l,r,k); pushup(p); } void change2(int p,int l,int r,int k) { if(tr[p].l>r||tr[p].r<l)return; if(l<=tr[p].l&&tr[p].r<=r) { tr[p].s+=k*(tr[p].r-tr[p].l+1);tr[p].lazy+=k; mod(tr[p].s);mod(tr[p].lazy); return ; } pushdown(p); change2(lc(p),l,r,k);change2(rc(p),l,r,k); pushup(p); } int query(int p,int x) { if(tr[p].l>x||tr[p].r<x)return 0; if(tr[p].l==tr[p].r)return tr[p].s; pushdown(p); return query(lc(p),x)+query(rc(p),x); } signed main() { int n,q;cin>>n>>q; for(int i=1;i<=n;i++)cin>>a[i]; bt(1,1,n); while(q--) { int op,l,r,b,c;cin>>op; if(op==0) { cin>>l>>r>>b>>c;l++; change1(1,l,r,b);change2(1,l,r,c); } else { cin>>l;l++; cout<<query(1,l)<<'\n'; } } return 0; }
- 1
信息
- ID
- 8124
- 时间
- 1000ms
- 内存
- 1024MiB
- 难度
- 7
- 标签
- 递交数
- 58
- 已通过
- 13
- 上传者