廈門大學程序設計大賽月賽(同步賽)(D 線段樹 區間加,區間乘,區間查詢,區間覆蓋)

題目鏈接

這題寫了我兩個小時,在cf延時的15分鐘內調出來了,直呼內行

D-小C的棋王之路

給個節點用k*x+val 表示lazy更新   初始葉子節點k=1 val=a[l]  其他  k=1  val=0

一個mul數組,記錄每個節點的前面的係數k,val數組記錄後面val的值  sum數組記錄區間和,因爲詢問的是區間和

每次區間乘了一個k:

某個節點記錄:

mul[id]*=k

val[id]*=k

sum[id]*=k

mul[id]=k*mul[id]%mod;
val[id]=k*val[id]%mod;
sum[id]=k*sum[id]%mod;

區間加了一個k:

val[id]+=k

sum[id]+k*(r-l+1) (l,r是某個節點的信息)

add(val[id],k);
add(sum[id],k*(r-l+1)%mod);

區間覆蓋:(驚天妙手,突然想到的處理方式)

mul[id]=0;
val[id]=k;

 sum[id]=k*(r-l+1)

mul[id]=0;
val[id]=k;
sum[id]=k*(r-l+1)%mod;

lazy更新:相當於某個節點同時來k倍係數以及加了個 後綴的x值

假設k、x是由id的父親節點傳來,

mul[id]*=k;

val[id]=x+k*val[id]

sum[id]=sum[id]*k+x*(r-l+1)

int root=id,len=r-l+1;
ll p=mod;
mul[id<<1]=mul[id]*mul[id<<1]%mod;
val[id<<1]=(val[id]+val[id<<1]*mul[id]%mod)%mod;
sum[root<<1]=(sum[root<<1]*mul[root]%p+val[root]*(len-(len>>1))%p)%p;

mul[id<<1|1]=mul[id]*mul[id<<1|1]%mod;
val[id<<1|1]=(val[id]+val[id<<1|1]*mul[id]%mod)%mod;
sum[root<<1|1]=(sum[root<<1|1]*mul[root]%p+val[root]*(len>>1)%p)%p;

 

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define maxn 1005
#define inf 1e9
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
using namespace std;

inline ll read()
{
	ll x=0,w=1; char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') w=-1; c=getchar();}
	while(c<='9'&&c>='0') {x=(x<<1)+(x<<3)+c-'0'; c=getchar();}
	return w==1?x:-x;
}
const int N=2e5+10;
ll n,m,mod;
int mx;
struct node
{
    int ty,l,r;
    ll k;
}a[N];
ll mul[4*N],val[4*N],sum[4*N],t[N];
int st[4*N];
void add(ll &x,ll y)
{
    x=(x+y)%mod;
}
void build(int id,int l,int r)
{
    mul[id]=1;
    if(l==r){
       sum[id]=t[l];
        return ;
    }
    int mid=l+r>>1;
    build(id<<1,l,mid);
    build(id<<1|1,mid+1,r);
    sum[id]=(sum[id<<1]+sum[id<<1|1])%mod;
}
void pushdown(int id,int l,int r)
{
    int mid=l+r>>1;

    if(mul[id]==1&&val[id]==0) return;


    int root=id,len=r-l+1;
    ll p=mod;
    mul[id<<1]=mul[id]*mul[id<<1]%mod;
    val[id<<1]=(val[id]+val[id<<1]*mul[id]%mod)%mod;
    sum[root<<1]=(sum[root<<1]*mul[root]%p+val[root]*(len-(len>>1))%p)%p;

    mul[id<<1|1]=mul[id]*mul[id<<1|1]%mod;
    val[id<<1|1]=(val[id]+val[id<<1|1]*mul[id]%mod)%mod;
    sum[root<<1|1]=(sum[root<<1|1]*mul[root]%p+val[root]*(len>>1)%p)%p;

    mul[id]=1,val[id]=0;
}
ll qu(int id,int l,int r,int ql,int qr)
{
    if(ql<=l&&r<=qr) return sum[id];
    int mid=l+r>>1;
    ll ans=0;
    pushdown(id,l,r);
    if(ql<=mid) ans=qu(id<<1,l,mid,ql,qr);
    if(qr>mid) add(ans,qu(id<<1|1,mid+1,r,ql,qr));
    //sum[id]=(sum[id<<1|1]+sum[id<<1])%mod;
    return ans;
}

void up(int id,int l,int r,int ql,int qr,ll k,int ty)
{
    if(ql<=l&&r<=qr){
        if(ty==1){
            //printf("id:%d sum[id]:%lld\n",id,sum[id]);

            add(val[id],k);
            add(sum[id],k*(r-l+1)%mod);
            //printf("id:%d sum[id]:%lld\n",id,sum[id]);
        }
        else if(ty==2){
            mul[id]=k*mul[id]%mod;
            val[id]=k*val[id]%mod;
            sum[id]=k*sum[id]%mod;
        }
        else if(ty==3){
            st[id]=-1;
            mul[id]=0;
            val[id]=k;
            sum[id]=k*(r-l+1)%mod;
        }
        else{
            mul[id]=1,val[id]=k;

            sum[id]=k*(r-l+1)%mod;
        }
        return ;
    }
    pushdown(id,l,r);
    int mid=l+r>>1;
    if(ql<=mid) up(id<<1,l,mid,ql,qr,k,ty);
    if(qr>mid) up(id<<1|1,mid+1,r,ql,qr,k,ty);
    sum[id]=(sum[id<<1|1]+sum[id<<1])%mod;
}
int main()
{
    n=read(),m=read(),mod=read();
    mx=n;
    rep(i,1,n) t[i]=read();

    for(int i=1;i<=m;++i){
        scanf("%d%d",&a[i].ty,&a[i].l);
        if(a[i].ty==5) scanf("%d",&a[i].r);
        else if(a[i].ty==4) mx++;
        else scanf("%d%lld",&a[i].r,&a[i].k),a[i].k%=mod;
        a[i].r=min(a[i].r,mx);
        a[i].r=min(a[i].r,mx);
    }

    build(1,1,mx);

    int now=n;
    for(int i=1;i<=m;++i){
        if(a[i].ty==1){
           up(1,1,mx,a[i].l,a[i].r,a[i].k,1);
        }
        else if(a[i].ty==2){
           up(1,1,mx,a[i].l,a[i].r,a[i].k,2);
        }
        else if(a[i].ty==3){
           up(1,1,mx,a[i].l,a[i].r,a[i].k,3);
        }
        else if(a[i].ty==4){
           up(1,1,mx,++now,now,a[i].l,4);
        }
        else if(a[i].ty==5){
           printf("%lld\n",qu(1,1,mx,a[i].l,a[i].r));
        }
    }
}
/*
5 6 9555
1 1 1 1 1
3 2 5 5
5 1 5
1 1 4 5
1 1 5 5
1 3 5 5
5 1 4


5 12 9555
1 1 1 1 1
3 2 5 5
1 1 4 5
1 1 5 5
1 3 5 5
5 1 4

2 1 5 5
2 2 2 5
3 5 5 5
3 3 5 5
5 1 3
1 2 3 5
5 1 3


*/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章